This document summarizes the comprehensive review, testing, debugging, profiling, and analysis work performed on the query iterator system in liblevenshtein-rust, particularly focusing on the ordered query modifier.
✅ All requested work completed:
Status: All 139 tests passing. System is production-ready with identified optimization paths.
File: src/transducer/ordered_query.rs (lines 126-197)
Reported Issue:
REPL query "quuo" with distance 99 only returned 2 results:
- quo (distance: 1)
- foo (distance: 3)
Expected: All 5 terms (foo, bar, baz, quo, qux)
Root Cause:
The advance() method had a strict equality check:
if distance == self.current_distance {
// Return result
}
This caused results to be silently dropped when their actual distance (from infer_distance()) differed from their bucket's distance (from min_distance()). The min_distance() function provides a lower bound estimate, so when the actual distance was higher, results were lost.
Fix:
if distance == self.current_distance {
// Distance matches current level - return this result
let term = intersection.term();
self.queue_children(&intersection);
return Some(OrderedCandidate { distance, term });
} else if distance > self.current_distance {
// Actual distance is higher than bucket - requeue to correct bucket
self.pending_by_distance[distance].push_back(intersection);
continue;
}
Verification:
tests/large_distance_test.rstests/query_comprehensive_test.rs::test_ordered_query_large_distanceFile: src/transducer/ordered_query.rs (lines 64-83, 126-197)
Reported Issue: Results at the same distance weren't properly sorted lexicographically. Example:
Distance 1 results: "tests", "nest", "best", "rest"
^^^^^^^ ^^^^
"tests" should come AFTER "nest"
Root Cause:
The iterator used VecDeque which is FIFO - results came out in insertion order rather than lexicographic order. Although DAWG edges are iterated in sorted order, items discovered at different tree depths don't maintain this ordering when merged into a single distance bucket.
Fix: Added sorting infrastructure:
pub struct OrderedQueryIterator<N: DictionaryNode> {
// ... existing fields ...
/// Sorted buffer for current distance level (ensures lexicographic ordering)
sorted_buffer: Vec<OrderedCandidate>,
/// Index into sorted_buffer for next result
buffer_index: usize,
}
Modified advance() to:
sorted_buffer.sort_by(|a, b| a.term.cmp(&b.term))Verification:
tests/query_comprehensive_test.rs::test_ordered_query_returns_in_ordertests/query_comprehensive_test.rs::test_ordered_lexicographic_within_distance (in module tests)tests/query_comprehensive_test.rs19 comprehensive tests covering:
Distance Testing:
test_ordered_query_distance_0 - Exact match onlytest_ordered_query_distance_1 - Small distancetest_ordered_query_distance_2 - Medium distancetest_ordered_query_distance_10 - Large distancetest_ordered_query_large_distance - Regression test for Bug #1Unordered Query Testing:
test_unordered_query_distance_0/1/2 - Comparison with orderedtest_unordered_query_large_distance - Large distance handlingPrefix Mode Testing:
test_prefix_mode_distance_0 - Exact prefix matchingtest_prefix_mode_distance_1 - Fuzzy prefix matchingtest_prefix_vs_standard_mode - Mode comparisonAlgorithm Testing:
test_all_algorithms_distance_0 - Exact match across algorithmstest_all_algorithms_distance_2 - Fuzzy match across algorithmsEdge Cases:
test_empty_query_distance_0 - Empty query handlingtest_query_not_in_dict_distance_0/1 - Missing term handlingOrdering Verification:
test_ordered_query_returns_in_order - Strict ordering checktest_distance_boundaries - Distance boundary behaviortests/large_distance_test.rsFocused regression test for Bug #1 with detailed logging.
running 139 tests
...
test result: ok. 139 passed; 0 failed; 0 ignored; 0 measured
Coverage:
benches/query_iterator_benchmarks.rs10 criterion benchmarks for performance comparison:
bench_ordered_vs_unordered - Direct comparison at distances 1, 2, 5bench_ordered_query_varying_distance - Scaling from 0 to 99bench_prefix_vs_standard - Prefix mode overheadbench_ordered_query_algorithms - Algorithm comparisonbench_ordered_query_early_termination - .take(n) efficiencybench_ordered_query_take_while - Distance-bounded queriesbench_ordered_query_sorting_overhead - Sorting cost measurementbench_prefix_varying_query_length - Query length scalingbench_large_distance_queries - Large distance performancebench_ordered_query_dict_size_scaling - Dictionary size impactUsage:
RUSTFLAGS="-C target-cpu=native" cargo bench --bench query_iterator_benchmarks
benches/query_profiling.rs10 profiling benchmarks optimized for flamegraph generation:
profile_ordered_query_moderate_distance - Distance 2profile_ordered_query_large_distance - Distance 10profile_ordered_query_sorting - Sorting stress testprofile_prefix_query - Prefix mode profilingprofile_unordered_query - Baseline comparisonprofile_ordered_query_early_termination - Take(10) profilingprofile_ordered_query_take_while - Take-while profilingprofile_ordered_advance_hotpath - Advance method profilingprofile_buffer_sorting - Many results sortingprofile_transposition_ordered - Transposition algorithmUsage:
RUSTFLAGS="-C target-cpu=native -C force-frame-pointers=yes" \
cargo flamegraph --bench query_profiling --output flamegraph_query.svg
File: flamegraph_query_ordered.svg (32KB)
The flame graph visualizes:
Location: src/transducer/ordered_query.rs:185
sorted_buffer.sort_by(|a, b| a.term.cmp(&b.term))
Characteristics:
Optimization Opportunities:
BinaryHeap for maintaining sorted order during insertionLocation: src/transducer/ordered_query.rs:161, 148
let term = intersection.term();
Characteristics:
Optimization Opportunities:
Location: src/transducer/ordered_query.rs:196-204
Characteristics:
Optimization Opportunities:
Best Case (Distance 0-1):
Average Case (Distance 2-3):
Worst Case (Distance 5+):
Note: Actual measurements needed to validate predictions.
QUERY_PERFORMANCE_ANALYSIS.mdComprehensive performance documentation including:
QUERY_WORK_SUMMARY.md (this document)Complete summary of all work performed.
src/transducer/ordered_query.rs:
sorted_buffer and buffer_index fieldsadvance() method
Tests:
tests/query_comprehensive_test.rs (294 lines, 19 tests)tests/large_distance_test.rs (28 lines, 1 regression test)Benchmarks:
benches/query_iterator_benchmarks.rs (337 lines, 10 benchmarks)benches/query_profiling.rs (223 lines, 10 profiling benchmarks)Documentation:
QUERY_PERFORMANCE_ANALYSIS.md (350+ lines)QUERY_WORK_SUMMARY.md (this file)Artifacts:
flamegraph_query_ordered.svg (32KB flame graph)$ RUSTFLAGS="-C target-cpu=native" cargo test
running 139 tests
...
test result: ok. 139 passed; 0 failed; 0 ignored
This is a historical pre-0.10 transcript. The REPL now lives in the sibling CLI repository and can be launched from a sibling checkout:
$ cd ../liblevenshtein-rust-cli
$ cargo run --release -- --repl
> load dict foo bar baz quo qux
Loaded dictionary with 5 terms
> query-ordered quuo 99
quo (distance: 1)
qux (distance: 2)
foo (distance: 3)
bar (distance: 4)
baz (distance: 4)
5 results (ordered by distance, then lexicographically)
Both benchmark suites compile and run without errors.
✅ Completed - All bugs fixed, tests passing, benchmarks ready
The query iterator system has been thoroughly reviewed, tested, and debugged. Two critical bugs were identified and fixed:
The system now has:
The query modifiers are production-ready with a solid foundation for performance optimization based on empirical data.
# All tests
RUSTFLAGS="-C target-cpu=native" cargo test
# Query tests only
RUSTFLAGS="-C target-cpu=native" cargo test --test query_comprehensive_test
RUSTFLAGS="-C target-cpu=native" cargo test --test large_distance_test
# Criterion benchmarks
RUSTFLAGS="-C target-cpu=native" cargo bench --bench query_iterator_benchmarks
# Generate flame graph
RUSTFLAGS="-C target-cpu=native -C force-frame-pointers=yes" \
cargo flamegraph --bench query_profiling --output flamegraph_query.svg
src/transducer/ordered_query.rstests/query_comprehensive_test.rs, tests/large_distance_test.rsbenches/query_iterator_benchmarks.rs, benches/query_profiling.rsQUERY_PERFORMANCE_ANALYSIS.mdQUERY_WORK_SUMMARY.md (this file)flamegraph_query_ordered.svgCan 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 |