Sassy 0.2.6, AVX2, one thread pinned to CPU 19 on an Intel Core i5-13500. Medians of seven runs after a warm-up, with inputs resident before timing. The adapter benchmark describes the timing boundaries and workloads: 262,144 DNA records and 4,096 dense ASCII records. The baseline includes cached DuckDB vector handles.
| Workload | Path | Before (s) | After (s) | Elapsed time reduction (%) |
|---|---|---|---|---|
| ascii | ffi | 0.137 | 0.134 | 2.3 |
| ascii | sql | 0.165 | 0.164 | 0.6 |
| ascii | upstream | 0.132 | 0.132 | 0.0 |
| dna | ffi | 0.755 | 0.751 | 0.5 |
| dna | sql | 0.811 | 0.773 | 4.7 |
| dna | upstream | 0.711 | 0.706 | 0.7 |
DNA SQL elapsed time falls from 0.811 s to 0.773 s (4.7%). The direct upstream median also falls by 0.7%; these sequential runs include run-to-run variation. The native FFI DNA change is small, and the dense ASCII SQL change is 1 ms. These measurements support a modest SQL improvement on the DNA workload; they do not establish a general speedup across inputs or separate the effects of buffer reuse from successful-call bookkeeping.
SQL takes about 9.5% longer than direct upstream calls for DNA and 24.1% longer for dense ASCII in the after measurements. SQL includes database execution, result materialization, aggregation and persistent CLI/R communication. The FFI path excludes the C runtime dispatcher. Both native paths use the same executable, dependency and compiler flags.
Each searcher can retain one consumed result, including its hit and CIGAR buffer
capacity. SQL returns each consumed result to its searcher; the native FFI
benchmark uses the same sassy_c_result_recycle() operation. Searcher destruction
releases that retained storage. Actual errors still allocate their diagnostic
strings; successful calls use a static empty error string.
Tests count allocations on the calling thread and verify zero allocations for:
These checks cover adapter overhead. Searches with hits still allocate in upstream Sassy and during per-hit CIGAR formatting. Packed CIGAR output remains the subject of issue #6.
Lifecycle tests check that recycling clears lengths and retains capacity, outstanding results survive other searches, and owned results remain valid after their searcher is destroyed. A recycled result and its borrowed views must no longer be used.
| workload | records | bytes | hits | full_hit_multisets_equal |
|---|---|---|---|---|
| dna | 262144 | 67108864 | 262676 | TRUE |
| ascii | 4096 | 1048576 | 524288 | TRUE |
Both native paths and SQL return identical full hit multisets, including coordinates, cost, strand and CIGAR. Timed runs also check count, cost sum and CIGAR bytes. The separate upstream CRISPR CLI oracle passes all 36 option profiles, covering 864 guide/record comparisons.
Build the AVX2 benchmark executable using the command in the adapter benchmark, then run from the repository root:
DUCKHTS_CACHE_DIR=/tmp/ducksassy-benchmark-cache R_LIBS=.deps/Rlib \
Rscript benchmarks/adapter_overhead.R local
R_LIBS=.deps/Rlib Rscript tools/render_readme.R benchmarks/buffer_reuse.Rmd
Choose the cache directory for your installation. Raw
before timings,
after timings and their
before receipt and
after receipt retain
artifact hashes, inputs and machine details. The baseline is commit
ff0c363487d24eb13eb06d1cd3001d0cc49631d6; the optimized build was measured
before commit and is identified by the artifact and source hashes in its receipt.