Skip to content

Commit d155fa9

Browse files
committed
chore: consider only systematic search on benchmark
1 parent bc04f77 commit d155fa9

File tree

2 files changed

+72
-91
lines changed

2 files changed

+72
-91
lines changed

README.md

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -162,59 +162,63 @@ For planning purposes, consider the 99th percentile times shown in the table abo
162162
### Real world example using the `benchmark` command
163163
```bash
164164
$ cargo run --release -F alkali -- benchmark -i 1 -t 16
165+
Using 16 threads for benchmark
166+
Starting benchmark with 1 iterations across 16 threads...
167+
165168
Benchmark results:
166169
Threads: 16
167-
Total time: 30.79s
170+
Total time: 30.51s
168171
Total iterations: 16
169-
Global average time per derivation: 1924.35ms
172+
Global average time per derivation: 1907.07ms
170173
Global derivations per second: 0.52
171-
Thread average time per derivation: 30.79s
174+
Thread average time per derivation: 30.51s
172175
Thread derivations per second: 0.03
173176

174177
Estimated time to brute-force one preimage/key pair:
175-
bits │ systematic (worst) │ random (expected) │ random (99th %ile) │ random (99.9th %ile)
176-
-----┼--------------------┼--------------------┼--------------------┼-------------------
177-
1 │ 31s │ 31s │ 2min 22s │ 3min 33s
178-
2 │ 31s │ 31s │ 2min 22s │ 3min 33s
179-
3 │ 31s │ 31s │ 2min 22s │ 3min 33s
180-
4 │ 31s │ 31s │ 2min 22s │ 3min 33s
181-
5 │ 31s │ 31s │ 2min 22s │ 3min 33s
182-
6 │ 1min 2s │ 31s │ 2min 22s │ 3min 33s
183-
7 │ 2min 3s │ 1min 2s │ 4min 44s │ 7min 5s
184-
8 │ 4min 6s │ 2min 3s │ 9min 27s │ 14min 11s
185-
9 │ 8min 13s │ 4min 6s │ 18min 54s │ 28min 21s
186-
10 │ 16min 25s │ 8min 13s │ 37min 49s │ 56min 43s
187-
11 │ 32min 51s │ 16min 25s │ 1h 16min │ 1h 53min
188-
12 │ 1h 6min │ 32min 51s │ 2h 31min │ 3h 47min
189-
13 │ 2h 11min │ 1h 6min │ 5h 2min │ 7h 34min
190-
14 │ 4h 23min │ 2h 11min │ 10h 5min │ 15h 7min
191-
15 │ 8h 45min │ 4h 23min │ 20h 10min │ 1d 6h
192-
16 │ 17h 31min │ 8h 45min │ 1d 16h │ 2d 12h
193-
17 │ 1d 11h │ 17h 31min │ 3d 9h │ 5d 1h
194-
18 │ 2d 22h │ 1d 11h │ 6d 17h │ 10d 2h
195-
19 │ 5d 20h │ 2d 22h │ 13d 11h │ 20d 4h
196-
20 │ 11d 16h │ 5d 20h │ 26d 21h │ 40d 8h
197-
21 │ 23d 9h │ 11d 16h │ 53d 19h │ 80d 16h
198-
22 │ 46d 17h │ 23d 9h │ 107d 13h │ 161d 8h
199-
23 │ 93d 10h │ 46d 17h │ 215d 2h │ 322d 16h
200-
24 │ 186d 20h │ 93d 10h │ 1y 65d │ 1y 280d
201-
25 │ 1y 8d │ 186d 20h │ 2y 130d │ 3y 195d
202-
26 │ 2y 17d │ 1y 8d │ 4y 260d │ 7y 24d
203-
27 │ 4y 34d │ 2y 17d │ 9y 154d │ 14y 49d
204-
28 │ 8y 67d │ 4y 34d │ 18y 309d │ 28y 98d
205-
29 │ 16y 135d │ 8y 67d │ 37y 252d │ 56y 196d
206-
30 │ 32y 270d │ 16y 135d │ 75y 139d │ 113y 27d
207-
31 │ 65y 174d │ 32y 270d │ 150y 279d │ 226y 53d
208-
32 │ 130y 348d │ 65y 174d │ 301y 193d │ 452y 106d
209-
210-
Search strategy explanation:
211-
• Systematic search: Partitions search space among threads (worst-case time shown)
212-
• Random search: Each thread picks candidates randomly (follows geometric distribution)
213-
214-
Random search variance:
215-
• 50th percentile (median): ~0.7× expected time
216-
• 90th percentile: ~2.3× expected time
217-
• 99th percentile: ~4.6× expected time
218-
• 99.9th percentile: ~6.9× expected time
178+
Note: This benchmark uses 16 threads with systematic search
179+
For comparison with random search percentiles, see README table
180+
181+
bits │ systematic (worst) │ systematic (avg)
182+
-----┼--------------------┼-------------------
183+
1 │ 31s │ 31s
184+
2 │ 31s │ 31s
185+
3 │ 31s │ 31s
186+
4 │ 31s │ 31s
187+
5 │ 31s │ 31s
188+
6 │ 1min 1s │ 31s
189+
7 │ 2min 2s │ 1min 1s
190+
8 │ 4min 4s │ 2min 2s
191+
9 │ 8min 8s │ 4min 4s
192+
10 │ 16min 16s │ 8min 8s
193+
11 │ 32min 33s │ 16min 16s
194+
12 │ 1h 5min │ 32min 33s
195+
13 │ 2h 10min │ 1h 5min
196+
14 │ 4h 20min │ 2h 10min
197+
15 │ 8h 41min │ 4h 20min
198+
16 │ 17h 22min │ 8h 41min
199+
17 │ 1d 11h │ 17h 22min
200+
18 │ 2d 21h │ 1d 11h
201+
19 │ 5d 19h │ 2d 21h
202+
20 │ 11d 14h │ 5d 19h
203+
21 │ 23d 3h │ 11d 14h
204+
22 │ 46d 7h │ 23d 3h
205+
23 │ 92d 14h │ 46d 7h
206+
24 │ 185d 4h │ 92d 14h
207+
25 │ 1y 5d │ 185d 4h
208+
26 │ 2y 10d │ 1y 5d
209+
27 │ 4y 20d │ 2y 10d
210+
28 │ 8y 41d │ 4y 20d
211+
29 │ 16y 81d │ 8y 41d
212+
30 │ 32y 162d │ 16y 81d
213+
31 │ 64y 324d │ 32y 162d
214+
32 │ 129y 283d │ 64y 324d
215+
216+
Systematic search explanation:
217+
• Worst-case: One thread gets unlucky and searches entire partition
218+
• Average case: Threads find target halfway through their partitions
219+
• No variance: Deterministic partitioning means predictable bounds
220+
221+
For random search with percentiles, see the README table comparing
222+
systematic (16 threads) vs random search (2048 threads)
219223
```
220224
---

wskdf-cli/src/main.rs

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -365,66 +365,43 @@ fn main() -> anyhow::Result<()> {
365365
eprintln!("Thread derivations per second: {thread_derivations_per_second:.2?}");
366366

367367
eprintln!("\nEstimated time to brute-force one preimage/key pair:");
368+
eprintln!("Note: This benchmark uses {threads} threads with systematic search");
369+
eprintln!("For comparison with random search percentiles, see README table");
370+
eprintln!();
368371
eprintln!(
369-
"{:>4} │ {:>18} │ {:>18} │ {:>18} │ {:>18}",
372+
"{:>4} │ {:>18} │ {:>18}",
370373
"bits",
371374
"systematic (worst)",
372-
"random (expected)",
373-
"random (99th %ile)",
374-
"random (99.9th %ile)"
375+
"systematic (avg)"
375376
);
376377
eprintln!(
377-
"{:->4}-┼-{:->18}-┼-{:->18}-┼-{:->18}-┼-{:->18}",
378-
"", "", "", "", ""
378+
"{:->4}-┼-{:->18}-┼-{:->18}",
379+
"", "", ""
379380
);
380381

381382
for bits in 1u8..=32 {
382383
// space = 2^(bits-1) because MSB is always 1
383384
let space: f64 = 2f64.powi(bits as i32 - 1); // 2^(n-1) candidates
384385

385-
// Systematic search: divide space among threads, worst case is entire partition
386-
let systematic_work = (space / threads as f64).max(1.0);
387-
let systematic_secs = systematic_work * thread_avg_time;
388-
389-
// Random search: expected trials = space/2, but distributed among threads
390-
let random_expected_work = (space / (2.0 * threads as f64)).max(1.0);
391-
let random_expected_secs = random_expected_work * thread_avg_time;
392-
let random_99th_secs = random_expected_secs * percentile_multiplier(0.99);
393-
let random_999th_secs = random_expected_secs * percentile_multiplier(0.999);
386+
// Systematic search: divide space among threads
387+
let systematic_worst_work = (space / threads as f64).max(1.0); // worst case: entire partition
388+
let systematic_avg_work = (space / (2.0 * threads as f64)).max(1.0); // average case: half partition
389+
let systematic_worst_secs = systematic_worst_work * thread_avg_time;
390+
let systematic_avg_secs = systematic_avg_work * thread_avg_time;
394391

395-
let systematic_human = pretty(systematic_secs);
396-
let random_human = pretty(random_expected_secs);
397-
let random_99th_human = pretty(random_99th_secs);
398-
let random_999th_human = pretty(random_999th_secs);
392+
let systematic_worst_human = pretty(systematic_worst_secs);
393+
let systematic_avg_human = pretty(systematic_avg_secs);
399394
eprintln!(
400-
"{bits:>4} │ {systematic_human:>18} │ {random_human:>18} │ {random_99th_human:>18} │ {random_999th_human:>18}"
395+
"{bits:>4} │ {systematic_worst_human:>18} │ {systematic_avg_human:>18}"
401396
);
402397
}
403398

404-
eprintln!("\nSearch strategy explanation:");
405-
eprintln!(
406-
"• Systematic search: Partitions search space among threads (worst-case time shown)"
407-
);
408-
eprintln!(
409-
"• Random search: Each thread picks candidates randomly (follows geometric distribution)"
410-
);
411-
eprintln!("\nRandom search variance:");
412-
eprintln!(
413-
"• 50th percentile (median): ~{:.1}× expected time",
414-
percentile_multiplier(0.50)
415-
);
416-
eprintln!(
417-
"• 90th percentile: ~{:.1}× expected time",
418-
percentile_multiplier(0.90)
419-
);
420-
eprintln!(
421-
"• 99th percentile: ~{:.1}× expected time",
422-
percentile_multiplier(0.99)
423-
);
424-
eprintln!(
425-
"• 99.9th percentile: ~{:.1}× expected time",
426-
percentile_multiplier(0.999)
427-
);
399+
eprintln!("\nSystematic search explanation:");
400+
eprintln!("• Worst-case: One thread gets unlucky and searches entire partition");
401+
eprintln!("• Average case: Threads find target halfway through their partitions");
402+
eprintln!("• No variance: Deterministic partitioning means predictable bounds");
403+
eprintln!("\nFor random search with percentiles, see the README table comparing");
404+
eprintln!("systematic (16 threads) vs random search (2048 threads)");
428405
}
429406
Commands::GenerateSalt { output } => {
430407
ensure_file_does_not_exists(&output, "output file already exists")?;

0 commit comments

Comments
 (0)