1- cat > src/main. rs << ' EOF '
21use std:: hint:: black_box;
32use std:: time:: Instant ;
43
@@ -22,6 +21,94 @@ fn bench<F: FnMut()>(trials: usize, iters: u64, mut f: F) -> f64 {
2221 median ( per_op)
2322}
2423
24+ fn inline_vs_periodic ( ) {
25+ const NBLOCKS : usize = 256 ;
26+ const OPS : usize = 200_000 ;
27+ const VICTIM : usize = 123 ;
28+ const TAMPER_AT : usize = OPS / 2 ;
29+
30+ let mut data = vec ! [ 0u8 ; NBLOCKS * BLOCK ] ;
31+ for ( i, b) in data. iter_mut ( ) . enumerate ( ) {
32+ * b = ( i as u32 ) . wrapping_mul ( 2654435761 ) as u8 ;
33+ }
34+ let leaves: Vec < [ u8 ; 32 ] > = ( 0 ..NBLOCKS )
35+ . map ( |i| * blake3:: hash ( & data[ i * BLOCK ..( i + 1 ) * BLOCK ] ) . as_bytes ( ) )
36+ . collect ( ) ;
37+
38+ let verify = |blk : & [ u8 ] , stored : & [ u8 ; 32 ] | -> bool {
39+ let h = blake3:: hash ( blk) ;
40+ let a = h. as_bytes ( ) ;
41+ let mut d = 0u8 ;
42+ for i in 0 ..32 {
43+ d |= a[ i] ^ stored[ i] ;
44+ }
45+ d == 0
46+ } ;
47+
48+ let mut s: u64 = 0x9E3779B97F4A7C15 ;
49+ let mut rng = || {
50+ s ^= s << 13 ;
51+ s ^= s >> 7 ;
52+ s ^= s << 17 ;
53+ s
54+ } ;
55+ let trace: Vec < usize > = ( 0 ..OPS ) . map ( |_| ( rng ( ) as usize ) % NBLOCKS ) . collect ( ) ;
56+
57+ let blk0 = & data[ VICTIM * BLOCK ..( VICTIM + 1 ) * BLOCK ] ;
58+ let inline_ns = bench ( 7 , 4000 , || {
59+ black_box ( verify ( black_box ( blk0) , & leaves[ VICTIM ] ) ) ;
60+ } ) ;
61+ let scan_ns = bench ( 7 , 200 , || {
62+ let mut bad = false ;
63+ for i in 0 ..NBLOCKS {
64+ bad |= !verify ( & data[ i * BLOCK ..( i + 1 ) * BLOCK ] , & leaves[ i] ) ;
65+ }
66+ black_box ( bad) ;
67+ } ) ;
68+
69+ let inline_detect = trace[ TAMPER_AT ..] . iter ( ) . position ( |& b| b == VICTIM ) ;
70+
71+ println ! ( ) ;
72+ println ! (
73+ "--- inline per-read vs periodic scan ({} blocks = {} KiB, {} ops) ---" ,
74+ NBLOCKS ,
75+ NBLOCKS * BLOCK / 1024 ,
76+ OPS
77+ ) ;
78+ println ! (
79+ "inline per-read : {:8.4} us/op | corrupted reads served = 0 | detection = next read of a block" ,
80+ inline_ns / 1000.0
81+ ) ;
82+ if let Some ( d) = inline_detect {
83+ println ! ( " (victim first re-read {} ops after tamper; caught there, 0 corrupt bytes served)" , d) ;
84+ }
85+ println ! (
86+ "{:>14} {:>12} {:>22} {:>16}" ,
87+ "scan_interval" , "amort_us/op" , "corrupted_reads_served" , "detect_window_ops"
88+ ) ;
89+ for & iv in & [ 1000usize , 10_000 , 50_000 , 100_000 ] {
90+ let mut next_scan = TAMPER_AT ;
91+ while next_scan % iv != iv - 1 {
92+ next_scan += 1 ;
93+ }
94+ let next_scan = next_scan. min ( OPS - 1 ) ;
95+ let corrupted = trace[ TAMPER_AT ..=next_scan]
96+ . iter ( )
97+ . filter ( |& & b| b == VICTIM )
98+ . count ( ) ;
99+ let amort = ( scan_ns / iv as f64 ) / 1000.0 ;
100+ println ! (
101+ "{:>14} {:>12.4} {:>22} {:>16}" ,
102+ iv,
103+ amort,
104+ corrupted,
105+ next_scan - TAMPER_AT
106+ ) ;
107+ }
108+ println ! ( "tradeoff: inline pays per read but serves 0 corrupted bytes; periodic is cheaper" ) ;
109+ println ! ( " per op as the interval grows, but serves corrupted data across the window." ) ;
110+ }
111+
25112fn main ( ) {
26113 let arch = std:: env:: consts:: ARCH ;
27114 println ! ( "axiom-bench-native arch={arch} (BLAKE3 std, runtime SIMD)" ) ;
@@ -51,5 +138,5 @@ fn main() {
51138 println ! ( ) ;
52139 println ! ( "speedup = proportional-access effect (platform-independent in shape)." ) ;
53140 println ! ( "absolute ms is specific to this CPU; label it arch={arch} in the paper." ) ;
141+ inline_vs_periodic ( ) ;
54142}
55- EOF
0 commit comments