Conducted comprehensive benchmarking to measure the impact of Profile-Guided Optimization on liblevenshtein-rust. Results show mixed performance impact with improvements in some operations but regressions in others.
Overall Assessment: PGO provides modest improvements for targeted workloads (1-4% in key operations) but shows regressions in construction and minimization (2-6%). The profiling workload focused on dictionary lookup operations, which explains why those improved while construction suffered.
RUSTFLAGS="-C target-cpu=native" cargo build --release
./pgo_build.sh
The profiling benchmark exercised:
Important: This workload emphasized lookup operations, which may not represent all use cases (e.g., construction-heavy workloads).
| Benchmark | PGO Change | Baseline | PGO | Impact |
|---|---|---|---|---|
dynamic_dawg_minimize/100 | -4.24% | 447.96 µs | 427.97 µs | 🔥 Significant |
dawg_edge_iteration/500 | -3.16% | 2.0190 µs | 1.9364 µs | ✅ Good |
dawg_contains/500 | -2.88% | 9.5380 µs | 9.4045 µs | ✅ Good |
dawg_edge_lookup/500 | -2.44% | 14.053 µs | 13.676 µs | ✅ Good |
dawg_contains/100 | -1.26% | 9.4230 µs | 9.2983 µs | ✅ Small |
dawg_contains/1000 | -1.16% | 9.7632 µs | 9.6097 µs | ✅ Small |
dawg_contains/5000 | -1.09% | 9.8161 µs | 9.7103 µs | ✅ Small |
Best improvement: dynamic_dawg_minimize/100 at -4.24%
Consistent wins: All dawg_contains benchmarks improved (1-3%)
| Benchmark | PGO Change | Baseline | PGO | Impact |
|---|---|---|---|---|
dawg_edge_iteration/100 | +6.04% | 2.0267 µs | 2.1419 µs | ⚠️ Regression |
dawg_edge_lookup/5000 | +5.10% | 16.046 µs | 16.451 µs | ⚠️ Regression |
dynamic_dawg_minimize/500 | +4.65% | 814.45 µs | 833.35 µs | ⚠️ Regression |
dynamic_dawg_minimize/1000 | +3.34% | 1.9421 ms | 2.0092 ms | ⚠️ Regression |
dawg_construction/100 | +2.62% | 95.761 µs | 99.052 µs | ⚠️ Small |
dawg_edge_lookup/1000 | +1.60% | 15.995 µs | 16.267 µs | 📊 Noise |
Biggest regression: dawg_edge_iteration/100 at +6.04%
Pattern: Construction and minimization operations slower with PGO
| Benchmark | PGO Change |
|---|---|
dawg_edge_lookup/100 | +0.77% (noise) |
dynamic_dawg_insertion/* | 0-1% (within noise) |
dawg_edge_iteration/1000 | -0.50% (noise) |
dawg_edge_iteration/5000 | -0.41% (noise) |
dawg_construction/500 | +1.43% (noise) |
dawg_construction/1000 | +1.24% (noise) |
dawg_construction/5000 | -0.58% (noise) |
1. Dictionary Lookup Operations (+1-3%)
contains() calls2. Edge Iteration for 500-term dictionaries (+3.2%)
3. Minimization for small dictionaries (+4.2%)
1. Construction Operations (-1-3%)
2. Edge Iteration for small dictionaries (-6%)
3. Minimization for medium/large dictionaries (-3-5%)
The profiling benchmark emphasized:
Recommendation: For applications that heavily construct DAWGs, PGO may not help or could hurt performance.
PGO provides marginal value for liblevenshtein-rust:
Recommendation:
Based on profiling (flame graphs), Arc reference counting overhead (41% of execution time) is a much bigger optimization target than PGO's 1-3% gains.
Priority ranking:
PGO is working as designed but provides limited value for liblevenshtein-rust:
Next recommended optimization: Tackle the Arc overhead (41%) identified in flame graph analysis. This has 10x more potential than PGO's 1-3% gains.
benchmark_no_pgo.txt - Baseline benchmarks (no PGO)benchmark_with_pgo.txt - PGO-optimized benchmarksbuild_baseline_no_pgo.txt - Baseline build logpgo_build_log_v2.txt - PGO build logpgo_build.sh - Automated PGO workflow scriptCan 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 |