Empirical testing identified the optimal threshold for switching from linear to binary search in edge lookup operations. By tuning the threshold from 8 to 16 edges, we achieved 20-21% performance improvement for larger dictionaries.
The DAWG implementation uses an adaptive search strategy:
The original threshold was set at 8 edges based on intuition. This analysis provides empirical evidence for the optimal threshold.
Analyzed the distribution of edge counts in DAWG nodes across different dictionary sizes:
| Dictionary Size | Nodes | Edge Count Distribution |
|---|---|---|
| 100 terms | 119 | 84% have 0 edges, 7% have 1 edge, 9% have 10 edges |
| 500 terms | 563 | 89% have 0 edges, 1% have 1 edge, 10% have 10 edges |
| 1000 terms | 1118 | 89% have 0 edges, 1% have 1 edge, 10% have 10 edges |
| 5000 terms | 5562 | 90% have 0 edges, 0.1% have 1 edge, 10% have 10 edges |
Key finding: Synthetic test data ("word000000" pattern) creates a bimodal distribution with 90% final/linear nodes and 10% branching nodes with exactly 10 edges.
Microbenchmarked both search strategies across different edge counts to find the crossover point:
| Edge Count | Linear Search | Binary Search | Winner | Advantage |
|---|---|---|---|---|
| 2 | 1.49 ns | 2.21 ns | Linear | 33% faster |
| 4 | 2.20 ns | 3.24 ns | Linear | 32% faster |
| 6 | 2.82 ns | 4.34 ns | Linear | 35% faster |
| 8 | 3.47 ns | 4.46 ns | Linear | 22% faster |
| 10 | 4.20 ns | 6.04 ns | Linear | 30% faster |
| 12 | 4.39 ns | 6.06 ns | Linear | 28% faster |
| 16 | 6.11 ns | 6.04 ns | TIE | ~0% |
| 20 | 7.24 ns | 7.87 ns | Linear | 8% faster |
| 26 | 9.22 ns | 7.92 ns | Binary | 14% faster |
Crossover point: 16-20 edges
With the original threshold of 8:
Updated threshold in both dawg.rs and dynamic_dawg.rs:
// Before: threshold=8
if edges.len() < 8 {
// linear search
} else {
// binary search
}
// After: threshold=16 (empirically validated)
if edges.len() < 16 {
// linear search
} else {
// binary search
}
| Dictionary Size | Threshold=8 | Threshold=16 | Improvement |
|---|---|---|---|
| 100 terms | 3.13 µs | 2.94 µs | -4.1% (1.04x faster) |
| 500 terms | 3.22 µs | 2.87 µs | -8.7% (1.10x faster) |
| 1000 terms | 3.84 µs | 3.03 µs | -21.6% (1.27x faster) |
| 5000 terms | 3.86 µs | 3.06 µs | -20.5% (1.26x faster) |
Average improvement: 13.7% across all sizes, with 20-21% for larger dictionaries
The improvement scales with dictionary size because the 10% of branching nodes becomes a larger absolute count.
Our test data ("word000000", "word000001", etc.) creates an artificial edge distribution:
English dictionaries would likely show:
With real data, threshold=16 would still be optimal or even conservative. A threshold of 20 might perform even better for English text.
Combining with Arc optimization (from previous work):
| Operation | Baseline | +Arc Opt | +Arc+Threshold | Total Improvement |
|---|---|---|---|---|
| contains/100 | 9.30 µs | 3.13 µs | 2.94 µs | -68.4% (3.16x faster) |
| contains/500 | 9.60 µs | 3.22 µs | 2.87 µs | -70.1% (3.35x faster) |
| contains/1000 | 9.61 µs | 3.84 µs | 3.03 µs | -68.5% (3.17x faster) |
| contains/5000 | 9.71 µs | 3.86 µs | 3.06 µs | -68.5% (3.17x faster) |
Combined optimizations deliver 3.2-3.4x speedup!
1. src/dictionary/dawg.rs
contains() methodtransition() method2. src/dictionary/dynamic_dawg.rs
transition() methodbenches/threshold_analysis.rs
benches/threshold_tuning.rs
✅ Apply threshold=16 - Validated by empirical testing, delivers 20-21% improvement
Consider threshold=20 for English dictionaries:
Empirical threshold tuning delivered 20-21% performance improvement for dictionary lookups:
Key Findings:
Optimization Applied:
Combined with Arc optimization: 3.2-3.4x total speedup for contains() operations
Analysis Results:
threshold_analysis_results.txt - Edge distribution analysisthreshold_tuning_results.txt - Linear vs binary crossover testingBenchmarks:
dawg_contains_threshold16.txt - Performance with optimized thresholdRelated Documentation:
docs/ARC_OPTIMIZATION_RESULTS.md - Arc overhead elimination (60% improvement)docs/DAWG_OPTIMIZATION_OPPORTUNITIES.md - Original optimization analysisCan you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |