code wiki / (root) / nx_bench_stats_test.nx

nx_bench_stats_test.nx source

↩ module page · 157 lines · 5832 B

1// nx_bench_stats_test.nx -- smoke for the distribution-stats primitive. 2 3import "nx_syscalls.nx" 4import "nx_tier.nx" 5import "nx_bench_stats.nx" 6 7func main() -> i64 { 8 // 1: verdict enum validity 9 if nx_bst_v_is_valid(NX_BST_OK) != 1 { return 1 } 10 if nx_bst_v_is_valid(NX_BST_NULL_SAMPLES) != 1 { return 2 } 11 if nx_bst_v_is_valid(NX_BST_EMPTY) != 1 { return 3 } 12 if nx_bst_v_is_valid(NX_BST_N) != 0 { return 4 } 13 if nx_bst_v_is_valid(-1) != 0 { return 5 } 14 15 // 2: empty + null + invalid 16 let stats: *NxBenchStats = nx_bst_new() 17 let null_samples: *i64 = (0 as i64) as *i64 18 if nx_bench_stats_compute(null_samples, 10, stats) != NX_BST_NULL_SAMPLES { return 6 } 19 let buf: *u8 = sys_mmap(80) 20 let samples: *i64 = buf as *i64 21 let null_stats: *NxBenchStats = (0 as i64) as *NxBenchStats 22 if nx_bench_stats_compute(samples, 10, null_stats) != NX_BST_NULL_OUT { return 7 } 23 if nx_bench_stats_compute(samples, 0, stats) != NX_BST_EMPTY { return 8 } 24 if nx_bench_stats_compute(samples, -1, stats) != NX_BST_EMPTY { return 9 } 25 26 // 3: known distribution -- 10 samples ascending 27 // [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] 28 samples[0] = 10 29 samples[1] = 20 30 samples[2] = 30 31 samples[3] = 40 32 samples[4] = 50 33 samples[5] = 60 34 samples[6] = 70 35 samples[7] = 80 36 samples[8] = 90 37 samples[9] = 100 38 39 if nx_bench_stats_compute(samples, 10, stats) != NX_BST_OK { return 10 } 40 if nx_bst_n(stats) != 10 { return 11 } 41 if nx_bst_min(stats) != 10 { return 12 } 42 if nx_bst_max(stats) != 100 { return 13 } 43 if stats.sum != 550 { return 14 } 44 if nx_bst_mean(stats) != 55 { return 15 } 45 // p50: samples[10/2] = samples[5] = 60 (post-sort, which already was sorted) 46 if nx_bst_p50(stats) != 60 { return 16 } 47 // p95: samples[(95*9)/100] = samples[8] = 90 48 if nx_bst_p95(stats) != 90 { return 17 } 49 50 // 4: unsorted input -- min/max/percentiles still correct after sort 51 let buf2: *u8 = sys_mmap(80) 52 let s2: *i64 = buf2 as *i64 53 s2[0] = 50; s2[1] = 10; s2[2] = 90; s2[3] = 30; s2[4] = 70 54 s2[5] = 20; s2[6] = 80; s2[7] = 40; s2[8] = 100; s2[9] = 60 55 let st2: *NxBenchStats = nx_bst_new() 56 if nx_bench_stats_compute(s2, 10, st2) != NX_BST_OK { return 18 } 57 if nx_bst_min(st2) != 10 { return 19 } 58 if nx_bst_max(st2) != 100 { return 20 } 59 if nx_bst_mean(st2) != 55 { return 21 } 60 if nx_bst_p50(st2) != 60 { return 22 } 61 if nx_bst_p95(st2) != 90 { return 23 } 62 // Array should now be sorted ascending 63 if s2[0] != 10 { return 24 } 64 if s2[9] != 100 { return 25 } 65 var i: nx_int = 1 66 while i < 10 { 67 if s2[i] < s2[i - 1] { return 26 } 68 i = i + 1 69 } 70 71 // 5: single-sample distribution 72 let buf3: *u8 = sys_mmap(8) 73 let s3: *i64 = buf3 as *i64 74 s3[0] = 42 75 let st3: *NxBenchStats = nx_bst_new() 76 if nx_bench_stats_compute(s3, 1, st3) != NX_BST_OK { return 27 } 77 if nx_bst_min(st3) != 42 { return 28 } 78 if nx_bst_max(st3) != 42 { return 29 } 79 if nx_bst_mean(st3) != 42 { return 30 } 80 if nx_bst_p50(st3) != 42 { return 31 } 81 if nx_bst_p95(st3) != 42 { return 32 } 82 if nx_bst_stddev(st3) != 0 { return 33 } 83 84 // 6: constant distribution -- stddev = 0 85 let buf4: *u8 = sys_mmap(40) 86 let s4: *i64 = buf4 as *i64 87 var k: nx_int = 0 88 while k < 5 { s4[k] = 100; k = k + 1 } 89 let st4: *NxBenchStats = nx_bst_new() 90 if nx_bench_stats_compute(s4, 5, st4) != NX_BST_OK { return 34 } 91 if nx_bst_stddev(st4) != 0 { return 35 } 92 if nx_bst_min(st4) != 100 { return 36 } 93 if nx_bst_max(st4) != 100 { return 37 } 94 95 // 7: stddev sanity -- [0, 100] should have stddev ~ 50 96 let buf5: *u8 = sys_mmap(16) 97 let s5: *i64 = buf5 as *i64 98 s5[0] = 0 99 s5[1] = 100 100 let st5: *NxBenchStats = nx_bst_new() 101 nx_bench_stats_compute(s5, 2, st5) 102 // mean=50; var = ((50)^2 + (50)^2)/2 = 2500; stddev = 50 103 if nx_bst_stddev(st5) != 50 { return 38 } 104 105 // 8: negative samples handled correctly 106 let buf6: *u8 = sys_mmap(40) 107 let s6: *i64 = buf6 as *i64 108 s6[0] = -50 109 s6[1] = -25 110 s6[2] = 0 111 s6[3] = 25 112 s6[4] = 50 113 let st6: *NxBenchStats = nx_bst_new() 114 nx_bench_stats_compute(s6, 5, st6) 115 if nx_bst_min(st6) != -50 { return 39 } 116 if nx_bst_max(st6) != 50 { return 40 } 117 if nx_bst_mean(st6) != 0 { return 41 } 118 119 // 9: accessor null guards 120 let null_st: *NxBenchStats = (0 as i64) as *NxBenchStats 121 if nx_bst_min(null_st) != 0 { return 42 } 122 if nx_bst_max(null_st) != 0 { return 43 } 123 if nx_bst_mean(null_st) != 0 { return 44 } 124 if nx_bst_p50(null_st) != 0 { return 45 } 125 if nx_bst_p95(null_st) != 0 { return 46 } 126 if nx_bst_stddev(null_st) != 0 { return 47 } 127 if nx_bst_n(null_st) != 0 { return 48 } 128 129 // 10: realistic wall-clock distribution -- 10 fake "elapsed_us" samples 130 // with some variance 131 let buf7: *u8 = sys_mmap(80) 132 let s7: *i64 = buf7 as *i64 133 s7[0] = 10500 // typical 134 s7[1] = 10200 135 s7[2] = 10800 136 s7[3] = 10100 137 s7[4] = 11500 // tail 138 s7[5] = 10300 139 s7[6] = 10400 140 s7[7] = 10600 141 s7[8] = 10700 142 s7[9] = 14000 // outlier 143 let st7: *NxBenchStats = nx_bst_new() 144 nx_bench_stats_compute(s7, 10, st7) 145 if nx_bst_min(st7) != 10100 { return 49 } 146 if nx_bst_max(st7) != 14000 { return 50 } 147 // sorted = [10100,10200,10300,10400,10500,10600,10700,10800,11500,14000] 148 // p50 = sorted[n/2] = sorted[5] = 10600 (simple-index median; 149 // even-n returns the upper-middle by convention here) 150 if nx_bst_p50(st7) != 10600 { return 51 } 151 // p95 = sorted[(95*9)/100] = sorted[8] = 11500 152 if nx_bst_p95(st7) != 11500 { return 52 } 153 // outlier inflates max; p95 doesn't see it (because index 8, not 9) 154 if nx_bst_max(st7) <= nx_bst_p95(st7) { return 53 } 155 156 return 0 157}