# include <fmt/core.h>
# include <string>
# include <fuc2/testing.hpp>
# include "stats.hpp"
using namespace fuc2 ;
namespace perf_tests {
struct LargeSOA {
std : : vector < int > a01 ;
std : : vector < int > a02 ;
std : : vector < int > a03 ;
std : : vector < int > a04 ;
std : : vector < int > a05 ;
std : : vector < int > a06 ;
std : : vector < int > a07 ;
std : : vector < int > a08 ;
std : : vector < int > a09 ;
std : : vector < int > a10 ;
std : : vector < int > a11 ;
std : : vector < int > a12 ;
std : : vector < int > a13 ;
std : : vector < int > a14 ;
std : : vector < int > a15 ;
std : : vector < int > a16 ;
std : : vector < int > a17 ;
std : : vector < int > a18 ;
std : : vector < int > a19 ;
std : : vector < int > 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 > s1 ;
std : : vector < S2 > s2 ;
std : : vector < S3 > s3 ;
std : : vector < S4 > s4 ;
std : : vector < S5 > 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 < Stats > soa_big_for ;
std : : vector < Stats > soa_many_for ;
std : : vector < Stats > ls_big_for ;
std : : vector < Stats > ls_many_for ;
std : : vector < Stats > maos_big_for ;
std : : vector < Stats > 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 < LargeStruct > ;
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 ) ,
}
} ;
}