Benchmarking & Performance
Relevant source files
The following files were used as context for generating this wiki page:
Keynobi is designed as a high-performance Android development companion, prioritizing low-latency data streaming and efficient memory management. The architecture focuses on handling high-frequency events, such as adb logcat and Gradle build outputs, without compromising the responsiveness of the SolidJS frontend or the stability of the Rust backend.
Performance is addressed through three primary strategies: bounded in-memory collections to prevent memory leaks, batching IPC communications to reduce bridge overhead, and utilizing the Criterion benchmarking framework for micro-optimizations.
Sources: README.md:151-158, AGENTS.md:27-28
Performance Architecture & Strategies
The system employs several architectural patterns to maintain performance under heavy load, particularly during active builds or high-volume logcat streaming.
Bounded Collections & Ring Buffers
To prevent unbounded memory growth, every in-memory collection is explicitly capped. Logcat entries and build logs utilize ring buffers, ensuring that memory usage remains flat regardless of the length of the development session.
| Component | Limit | Description |
|---|---|---|
| Logcat Ring Buffer | 50,000 entries | Stored in Rust; only visible entries are serialized to the frontend. |
| Build Log History | 10 records | Number of past build summaries kept in memory. |
| Build Log Buffer | 5,000 lines | Raw output lines retained for the current or last build. |
| Frontend Log Store | 10,000 lines | Maximum entries kept in the SolidJS build log store. |
Sources: README.md:151-153, src-tauri/src/services/build_runner.rs:14,75, src/stores/build.store.ts:47
Batching & Latency Reduction
The IPC (Inter-Process Communication) layer between Rust and the WKWebView frontend is a known bottleneck. To mitigate this, Keynobi avoids "one update per line" patterns.
- 100ms Logcat Batching:
adb logcatevents are batched at the Rust layer and emitted every 100ms to prevent flooding the SolidJS store. - 50ms Build Log Flushing: The frontend buffers incoming build lines and flushes them to the reactive store every 50ms.
Sources: README.md:154-155, src/stores/build.store.ts:89-105
Concurrent Task Management
The build_runner service manages long-running Gradle processes using asynchronous tokio tasks. It utilizes a oneshot channel to handle process exit signals, replacing less efficient polling loops.
Real-time Monitoring
The application includes built-in monitors for system resources, visible to the developer via the StatusBar. This allows for immediate detection of memory spikes or log file bloat.
Memory & Log Monitoring
- App Memory: Tracks the Resident Set Size (RSS) of the Keynobi process. Indicators turn yellow at 300MB and red at 500MB.
- Log Folder Size: Monitors the
~/.keynobi/directory. Rotation is triggered when the size exceeds user-defined limits (default 500MB). - Logcat Buffer Status: The Health Center monitors the 50K ring buffer usage and warns users when it exceeds 80% capacity to prevent loss of oldest entries.
Sources: src/components/layout/StatusBar.tsx:106-146, src/components/health/HealthPanel.tsx:501-525
Benchmarking Tools
Keynobi uses the Criterion library for Rust micro-benchmarks, allowing developers to measure the performance impact of changes to core services such as the file system manager or log parsers.
Benchmark Configuration
Benchmarks are defined in the src-tauri/Cargo.toml and executed via the Cargo test harness.
| Feature | Tool / Command | Purpose |
|---|---|---|
| Rust Benchmarks | cargo bench | Runs Criterion benchmarks; results in target/criterion/. |
| Performance Metrics | npm run perf:collect | Captures a snapshot of current performance metrics. |
| Metrics Reporting | npm run perf:report | Compares current metrics against the previous snapshot. |
Sources: AGENTS.md:42-47, src-tauri/Cargo.toml:50-54
Log Pipeline Optimization
The log_pipeline is a performance-critical path. To optimize entry enrichment, it avoids temporary allocations by using run_batch_into, which pushes processed entries directly into a provided target buffer.
Conclusion
Keynobi’s performance strategy is deeply integrated into its architectural constraints, notably through Mutex discipline (never holding locks across await), atomic file writes to prevent corruption during saves, and the use of specialized data structures like ring buffers. These optimizations ensure the tool remains lightweight while providing the real-time feedback necessary for Android development.
Sources: README.md:156-159