#include #include #include #include "stats.hpp" using namespace fuc2; namespace perf_tests { struct LargeSOA { std::vector a01; std::vector a02; std::vector a03; std::vector a04; std::vector a05; std::vector a06; std::vector a07; std::vector a08; std::vector a09; std::vector a10; std::vector a11; std::vector a12; std::vector a13; std::vector a14; std::vector a15; std::vector a16; std::vector a17; std::vector a18; std::vector a19; std::vector a20; void push_back(int x) { a01.push_back(x); a02.push_back(x); a03.push_back(x); a04.push_back(x); a05.push_back(x); a06.push_back(x); a07.push_back(x); a08.push_back(x); a09.push_back(x); a10.push_back(x); a11.push_back(x); a12.push_back(x); a13.push_back(x); a14.push_back(x); a15.push_back(x); a16.push_back(x); a17.push_back(x); a18.push_back(x); a19.push_back(x); a20.push_back(x); } }; struct LargeStruct { int a01; int a02; int a03; int a04; int a05; int a06; int a07; int a08; int a09; int a10; int a11; int a12; int a13; int a14; int a15; int a16; int a17; int a18; int a19; int a20; LargeStruct(int x) : a01(x), a02(x), a03(x), a04(x), a05(x), a06(x), a07(x), a08(x), a09(x), a10(x), a11(x), a12(x), a13(x), a14(x), a15(x), a16(x), a17(x), a18(x), a19(x), a20(x) {} }; struct S1 { int a01; int a02; int a03; int a04; S1(int x) : a01(x), a02(x), a03(x), a04(x) { } }; struct S2 { int a05; int a06; int a07; int a08; S2(int x) : a05(x), a06(x), a07(x), a08(x) { } }; struct S3 { int a09; int a10; int a11; int a12; S3(int x) : a09(x), a10(x), a11(x), a12(x) { } }; struct S4 { int a13; int a14; int a15; int a16; S4(int x) : a13(x), a14(x), a15(x), a16(x) { } }; struct S5 { int a17; int a18; int a19; int a20; S5(int x) : a17(x), a18(x), a19(x), a20(x) { } }; struct MultipleAOS { std::vector s1; std::vector s2; std::vector s3; std::vector s4; std::vector s5; void push_back(int x) { s1.push_back({x}); s2.push_back({x}); s3.push_back({x}); s4.push_back({x}); s5.push_back({x}); } }; struct Samples { std::vector soa_big_for; std::vector soa_many_for; std::vector ls_big_for; std::vector ls_many_for; std::vector maos_big_for; std::vector maos_many_for; }; void test_large_soa(Samples& samples, int sample_size, int sample_number) { auto soa = new LargeSOA(); for(int i = 0; i < sample_size; i++) { soa->push_back(i); } Stats big_for; for(int sample = 0; sample < sample_number; sample++) { auto start = big_for.time_start(); for(int i = 0; i < sample_size; i++) { soa->a01[i] += soa->a02[i] + sample; soa->a02[i] += soa->a03[i] + sample; soa->a03[i] += soa->a04[i] + sample; soa->a04[i] += soa->a05[i] + sample; soa->a05[i] += soa->a06[i] + sample; soa->a06[i] += soa->a07[i] + sample; soa->a07[i] += soa->a08[i] + sample; soa->a08[i] += soa->a09[i] + sample; soa->a09[i] += soa->a10[i] + sample; soa->a10[i] += soa->a11[i] + sample; soa->a11[i] += soa->a12[i] + sample; soa->a12[i] += soa->a13[i] + sample; soa->a13[i] += soa->a14[i] + sample; soa->a14[i] += soa->a15[i] + sample; soa->a15[i] += soa->a16[i] + sample; soa->a16[i] += soa->a17[i] + sample; soa->a17[i] += soa->a18[i] + sample; soa->a18[i] += soa->a19[i] + sample; soa->a19[i] += soa->a20[i] + sample; } big_for.sample_time(start); } samples.soa_big_for.push_back(big_for); Stats many_for; for(int sample = 0; sample < sample_number; sample++) { auto start = many_for.time_start(); for(int i = 0; i < sample_size; i++) soa->a01[i] += soa->a02[i] + sample; for(int i = 0; i < sample_size; i++) soa->a02[i] += soa->a03[i] + sample; for(int i = 0; i < sample_size; i++) soa->a03[i] += soa->a04[i] + sample; for(int i = 0; i < sample_size; i++) soa->a04[i] += soa->a05[i] + sample; for(int i = 0; i < sample_size; i++) soa->a05[i] += soa->a06[i] + sample; for(int i = 0; i < sample_size; i++) soa->a06[i] += soa->a07[i] + sample; for(int i = 0; i < sample_size; i++) soa->a07[i] += soa->a08[i] + sample; for(int i = 0; i < sample_size; i++) soa->a08[i] += soa->a09[i] + sample; for(int i = 0; i < sample_size; i++) soa->a09[i] += soa->a10[i] + sample; for(int i = 0; i < sample_size; i++) soa->a10[i] += soa->a11[i] + sample; for(int i = 0; i < sample_size; i++) soa->a11[i] += soa->a12[i] + sample; for(int i = 0; i < sample_size; i++) soa->a12[i] += soa->a13[i] + sample; for(int i = 0; i < sample_size; i++) soa->a13[i] += soa->a14[i] + sample; for(int i = 0; i < sample_size; i++) soa->a14[i] += soa->a15[i] + sample; for(int i = 0; i < sample_size; i++) soa->a15[i] += soa->a16[i] + sample; for(int i = 0; i < sample_size; i++) soa->a16[i] += soa->a17[i] + sample; for(int i = 0; i < sample_size; i++) soa->a17[i] += soa->a18[i] + sample; for(int i = 0; i < sample_size; i++) soa->a18[i] += soa->a19[i] + sample; for(int i = 0; i < sample_size; i++) soa->a19[i] += soa->a20[i] + sample; many_for.sample_time(start); } samples.soa_many_for.push_back(many_for); } void test_large_struct(Samples& samples, int sample_size, int sample_number) { auto ls = new std::vector; for(int i = 0; i < sample_size; i++) { ls->push_back({i}); } Stats ls_big_for; for(int sample = 0; sample < sample_number; sample++) { auto start = ls_big_for.time_start(); for(auto& el : *ls) { el.a01 += el.a02 + sample; el.a02 += el.a03 + sample; el.a03 += el.a04 + sample; el.a04 += el.a05 + sample; el.a05 += el.a06 + sample; el.a06 += el.a07 + sample; el.a07 += el.a08 + sample; el.a08 += el.a09 + sample; el.a09 += el.a10 + sample; el.a10 += el.a11 + sample; el.a11 += el.a12 + sample; el.a12 += el.a13 + sample; el.a13 += el.a14 + sample; el.a14 += el.a15 + sample; el.a15 += el.a16 + sample; el.a16 += el.a17 + sample; el.a17 += el.a18 + sample; el.a18 += el.a19 + sample; el.a19 += el.a20 + sample; } ls_big_for.sample_time(start); } samples.ls_big_for.push_back(ls_big_for); Stats ls_many_for; for(int sample = 0; sample < sample_number; sample++) { auto start = ls_many_for.time_start(); for(auto& el : *ls) el.a01 += el.a02 + sample; for(auto& el : *ls) el.a02 += el.a03 + sample; for(auto& el : *ls) el.a03 += el.a04 + sample; for(auto& el : *ls) el.a04 += el.a05 + sample; for(auto& el : *ls) el.a05 += el.a06 + sample; for(auto& el : *ls) el.a06 += el.a07 + sample; for(auto& el : *ls) el.a07 += el.a08 + sample; for(auto& el : *ls) el.a08 += el.a09 + sample; for(auto& el : *ls) el.a09 += el.a10 + sample; for(auto& el : *ls) el.a10 += el.a11 + sample; for(auto& el : *ls) el.a11 += el.a12 + sample; for(auto& el : *ls) el.a12 += el.a13 + sample; for(auto& el : *ls) el.a13 += el.a14 + sample; for(auto& el : *ls) el.a14 += el.a15 + sample; for(auto& el : *ls) el.a15 += el.a16 + sample; for(auto& el : *ls) el.a16 += el.a17 + sample; for(auto& el : *ls) el.a17 += el.a18 + sample; for(auto& el : *ls) el.a18 += el.a19 + sample; for(auto& el : *ls) el.a19 += el.a20 + sample; ls_many_for.sample_time(start); } samples.ls_many_for.push_back(ls_many_for); } void test_maos_style(Samples& samples, int sample_size, int sample_number) { auto maos = new MultipleAOS(); for(int i = 0; i < sample_size; i++) { maos->push_back(i); } Stats maos_big_for; for(int sample = 0; sample < sample_number; sample++) { auto start = maos_big_for.time_start(); for(int i = 0; i < sample_size; i++) { maos->s1[i].a01 += maos->s1[i].a02 + sample; maos->s1[i].a02 += maos->s1[i].a03 + sample; maos->s1[i].a03 += maos->s1[i].a04 + sample; maos->s1[i].a04 += maos->s2[i].a05 + sample; maos->s2[i].a05 += maos->s2[i].a06 + sample; maos->s2[i].a06 += maos->s2[i].a07 + sample; maos->s2[i].a07 += maos->s2[i].a08 + sample; maos->s2[i].a08 += maos->s3[i].a09 + sample; maos->s3[i].a09 += maos->s3[i].a10 + sample; maos->s3[i].a10 += maos->s3[i].a11 + sample; maos->s3[i].a11 += maos->s3[i].a12 + sample; maos->s3[i].a12 += maos->s4[i].a13 + sample; maos->s4[i].a13 += maos->s4[i].a14 + sample; maos->s4[i].a14 += maos->s4[i].a15 + sample; maos->s4[i].a15 += maos->s4[i].a16 + sample; maos->s4[i].a16 += maos->s5[i].a17 + sample; maos->s5[i].a17 += maos->s5[i].a18 + sample; maos->s5[i].a18 += maos->s5[i].a19 + sample; maos->s5[i].a19 += maos->s5[i].a20 + sample; } maos_big_for.sample_time(start); } samples.maos_big_for.push_back(maos_big_for); Stats maos_many_for; for(int sample = 0; sample < sample_number; sample++) { auto start = maos_many_for.time_start(); for(auto& el : maos->s1) { el.a01 += el.a02 + sample; el.a02 += el.a03 + sample; el.a03 += el.a04 + sample; } for(int i = 0; i < sample_size; i++) { maos->s1[i].a04 += maos->s2[i].a05 + sample; } for(auto& el : maos->s2) { el.a05 += el.a06 + sample; el.a06 += el.a07 + sample; el.a07 += el.a08 + sample; } for(int i = 0; i < sample_size; i++) { maos->s2[i].a08 += maos->s3[i].a09 + i; } for(auto& el : maos->s3) { el.a09 += el.a10 + sample; el.a10 += el.a11 + sample; el.a11 += el.a12 + sample; } for(int i = 0; i < sample_size; i++) { maos->s3[i].a12 += maos->s4[i].a13 + sample; } for(auto& el : maos->s4) { el.a13 += el.a14 + sample; el.a14 += el.a15 + sample; el.a15 += el.a16 + sample; } for(int i = 0; i < sample_size; i++) { maos->s4[i].a16 += maos->s5[i].a17 + sample; } for(auto& el : maos->s5) { el.a17 += el.a18 + sample; el.a18 += el.a19 + sample; el.a19 += el.a20 + sample; } maos_many_for.sample_time(start); } samples.maos_many_for.push_back(maos_many_for); } void test_all_performance() { Samples samples; int sample_size = 100; int sample_count = 100; for(int i = 0; i < 100; i++) { // quick and dirty "randomness" if(i % 2 == 0) { test_large_soa(samples, sample_size, sample_count); test_large_struct(samples, sample_size, sample_count); test_maos_style(samples, sample_count, sample_count); } else if(i % 3 == 0) { test_large_struct(samples, sample_size, sample_count); test_large_soa(samples, sample_size, sample_count); test_maos_style(samples, sample_count, sample_count); } else { test_maos_style(samples, sample_count, sample_count); test_large_struct(samples, sample_size, sample_count); test_large_soa(samples, sample_size, sample_count); } } fmt::println("soa_bf soa_mf ls_bf ls_mf maos_bf maos_mf"); Samples mofm; Stats soa_big_for; Stats soa_many_for; Stats ls_big_for; Stats ls_many_for; Stats maos_big_for; Stats maos_many_for; for(size_t i = 0; i < samples.soa_big_for.size(); i++) { fmt::println("{:.2f} {:.2f} {:.2f} {:.2f} {:.2f} {:.2f}", samples.soa_big_for[i].mean(), samples.soa_many_for[i].mean(), samples.ls_big_for[i].mean(), samples.ls_many_for[i].mean(), samples.maos_big_for[i].mean(), samples.maos_many_for[i].mean()); // this is potentially total bullshit soa_big_for.sample(samples.soa_big_for[i].mean()); soa_many_for.sample(samples.soa_many_for[i].mean()); ls_big_for.sample(samples.ls_big_for[i].mean()); ls_many_for.sample(samples.ls_many_for[i].mean()); maos_big_for.sample(samples.maos_big_for[i].mean()); maos_many_for.sample(samples.maos_many_for[i].mean()); } // totally not sure if this t-test is legit, must study more soa_big_for.t_test(ls_big_for); soa_big_for.t_test(maos_big_for); soa_many_for.t_test(ls_many_for); soa_many_for.t_test(maos_many_for); ls_many_for.t_test(maos_many_for); ls_big_for.t_test(maos_big_for); // the most pathologic case fmt::println("---- {}", soa_big_for.mean() - ls_many_for.mean()); soa_big_for.t_test(ls_many_for); } fuc2::Set TESTS{ .name="perf", .tests={ TEST(test_all_performance), } }; }