Performance
Benchmarks
sqry is built for speed at every layer. Key measured numbers:
| Metric | Value | Notes |
|---|---|---|
| Graph query latency | 12–21 ms | vs 1,300–2,400 ms for embedding-based search (100–200x faster) |
| JavaScript indexing throughput | 760K LOC/s | Measured with parallel graph indexing enabled |
| C++ indexing throughput | 1.1M LOC/s | — |
| Python indexing throughput | ~500K LOC/s | — |
| Cache speedup | 113x (452 ms → 4 ms) | Warm multiprocess-safe AST cache vs cold parse |
| Fuzzy candidate reduction | 99.8% | Jaccard trigram pre-filter on short queries |
The 113x cache speedup applies to repeated queries against an indexed codebase. The first query after sqry index loads the snapshot; subsequent queries (including across processes via the persistent cache) return in 4 ms.
Cache Environment Variables
sqry uses a two-layer cache: an in-memory eviction policy plus a persisted .sqry-cache/ directory. All cache settings are controlled by environment variables.
| Variable | Default | Description |
|---|---|---|
SQRY_CACHE_ROOT | .sqry-cache | Cache directory location |
SQRY_CACHE_MAX_BYTES | 50 MB | Maximum total cache size in bytes |
SQRY_CACHE_DISABLE_PERSIST | 0 | Set to 1 to disable disk persistence (memory-only; useful in CI/containers) |
SQRY_CACHE_POLICY | lru | Eviction policy: lru, tiny_lfu, or hybrid |
SQRY_CACHE_POLICY_WINDOW | 0.20 | Protected window ratio for TinyLFU and hybrid policies (range: 0.05–0.95) |
SQRY_CACHE_DEBUG | 0 | Set to 1 to emit CacheStats{...} on stderr without modifying CLI flags |
Choosing an eviction policy:
lru(default) — Least-recently-used. Best for general workloads where recent queries predict future queries.tiny_lfu— Windowed admission with a protected hot set. Best for large codebases with a stable set of frequently accessed symbols.hybrid— LRU window plus TinyLFU protected region. A compromise between the two.
Lexer Pool Tuning
The query lexer uses thread-local buffer pooling to reduce allocations on repeated queries. The defaults work for most workloads.
| Variable | Default | Description |
|---|---|---|
SQRY_LEXER_POOL_MAX | 4 | Pool size per thread. Set to 0 to disable pooling entirely. |
SQRY_LEXER_POOL_MAX_CAP | 256 | Buffer capacity limit in tokens before the pool shrinks a buffer |
SQRY_LEXER_POOL_SHRINK_RATIO | 8 | Shrink ratio applied when a buffer exceeds SQRY_LEXER_POOL_MAX_CAP |
Increase SQRY_LEXER_POOL_MAX for high-concurrency server workloads. Set it to 0 only when micro-benchmarking or when sub-millisecond latency requirements make per-allocation overhead relevant.
Cache Management Commands
# Show cache statistics (hit rates, size, entry counts)
sqry cache stats
# Show cache statistics as JSON (for monitoring/automation)
sqry cache stats --json
# Remove entries older than 30 days
sqry cache prune --days 30
# Cap cache to 1 GB, removing oldest entries first
sqry cache prune --size 1GB
# Preview what would be removed without deleting
sqry cache prune --days 7 --dry-run
# Clear all cached entries (requires --confirm to prevent accidental deletion)
sqry cache clear --confirm
Watch Mode
Watch mode keeps the index current with real-time file monitoring. sqry uses OS-level file system events (inotify on Linux, FSEvents on macOS, ReadDirectoryChangesW on Windows) with a debounce window to coalesce rapid saves.
# Start watching with an initial index build
sqry watch --build
# Show statistics for each incremental update
sqry watch --stats
# Set a custom debounce window in milliseconds (default: 100–400 ms, platform-dependent)
sqry watch --debounce 500
Watch mode is useful during active development: the index stays warm so sqry query returns up-to-date results without a manual sqry update step. Index update latency after a file save is typically under 1 ms for the file-detection step; the graph rebuild time depends on the number of changed files.
The debounce window (--debounce) controls how long sqry waits after the last file event before triggering a rebuild. Lower values give faster updates; higher values reduce redundant rebuilds when many files are saved in quick succession (for example, during a git checkout).
Index Validation
The --validate flag controls what happens when the index snapshot is loaded for queries. It does not run during the build itself.
# Load the index with strict validation; abort on any corruption
sqry index . --validate=fail --auto-rebuild
With --validate=fail --auto-rebuild, sqry will detect corruption when loading the snapshot, automatically trigger a full rebuild, and retry the query. This is the recommended setting for CI pipelines where a corrupted index would otherwise produce silent wrong results.
Other validation levels:
# Warn on validation errors but continue (default)
sqry query --validate=warn "kind:function" .
# Skip validation entirely (fastest, no safety net)
sqry query --validate=off "kind:function" .
Exit codes with --validate=fail:
0— Success1— Runtime error (file not found, permission denied)2— Validation error (corruption detected)