Documentation Index Fetch the complete documentation index at: https://mintlify.com/sohzm/jasonisnthappy/llms.txt
Use this file to discover all available pages before exploring further.
Jasonisnthappy is designed for high performance. This guide covers optimization techniques, benchmarks, and best practices.
Key metrics
Based on production benchmarks:
Bulk inserts ~19,000 docs/sec for 1000-doc batches
Single writes ~8ms per insert with full ACID guarantees
Reads Sub-millisecond queries on collections with 2500+ documents
Concurrent scaling Linear scaling with thread count up to core count
ACID compliance
All operations include:
Full ACID transaction support
MVCC snapshot isolation
Write-ahead logging (WAL)
Crash recovery
Performance numbers include durability guarantees (fsync). Jasonisnthappy doesn’t sacrifice safety for speed.
Write optimization
Batch operations
Use bulk inserts instead of individual inserts.
Fast: Bulk insert
Slow: Individual inserts
// Insert 1000 documents in one transaction
let docs : Vec < Value > = ( 0 .. 1000 )
. map ( | i | json! ({ "id" : i , "name" : format! ( "User {}" , i )}))
. collect ();
let ids = users . insert_many ( docs ) ? ; // ~50ms
// Throughput: ~19,000 docs/sec
Optimal batch size: 100-1000 documents per insert_many call balances throughput and memory usage.
Bulk write operations
Use bulk_write for mixed operations.
use jasonisnthappy :: Database ;
use serde_json :: json;
let users = db . collection ( "users" );
// Efficient: single transaction for multiple operations
let result = users . bulk_write ()
. insert ( json! ({ "name" : "Alice" }))
. insert ( json! ({ "name" : "Bob" }))
. update_one ( "name is \" Alice \" " , json! ({ "age" : 30 }))
. delete_many ( "status is \" inactive \" " )
. execute () ? ;
println! ( "Inserted: {}, Updated: {}, Deleted: {}" ,
result . inserted_count,
result . updated_count,
result . deleted_count
);
Unordered writes
For maximum throughput, use unordered bulk writes.
// Unordered: continue on errors, faster
let result = users . bulk_write ()
. ordered ( false ) // Don't stop on first error
. insert ( json! ({ "name" : "User1" }))
. insert ( json! ({ "name" : "User2" }))
// ... 100s of operations ...
. execute () ? ;
if ! result . errors . is_empty () {
eprintln! ( "Some operations failed: {:?}" , result . errors);
}
Checkpoint management
Control when WAL is checkpointed.
// Default: auto-checkpoint every 1000 WAL frames
let db = Database :: open ( "my.db" ) ? ;
// For bulk imports: increase threshold
db . set_auto_checkpoint_threshold ( 10000 ); // Checkpoint less often
// ... bulk insert operations ...
// Manual checkpoint after bulk import
db . checkpoint () ? ;
// Restore default
db . set_auto_checkpoint_threshold ( 1000 );
Increasing the checkpoint threshold reduces write amplification during bulk imports but uses more WAL space.
Read optimization
Use indexes
Indexes are crucial for query performance.
// Slow: scans entire collection
let user = users . find ( "email is \" alice@example.com \" " ) ? ;
// Time: O(n) - 50ms for 10,000 documents
// Fast: uses index lookup
db . create_index ( "users" , "email_idx" , "email" , true ) ? ;
let user = users . find ( "email is \" alice@example.com \" " ) ? ;
// Time: O(log n) - 0.02ms for 10,000 documents
See the Indexes guide for details.
Query optimization
Use the most specific query method.
// Best: Direct ID lookup
let user = users . find_by_id ( "user_123" ) ? ; // 0.01ms
// Good: find_one with index
let user = users . find_one ( "email is \" alice@example.com \" " ) ? ; // 0.02ms
// Slower: find (returns all matches)
let results = users . find ( "email is \" alice@example.com \" " ) ? ; // 0.03ms
let user = results . first ();
// Slowest: find_all then filter in code
let all_users = users . find_all () ? ; // 2ms for 10,000 docs
let user = all_users . iter () . find ( | u | u [ "email" ] == "alice@example.com" );
Projection
Fetch only the fields you need.
Fast: Project fields
Slow: Fetch everything
let results = users . query ()
. filter ( "age > 25" )
. project ( & [ "name" , "email" ]) // Only load 2 fields
. execute () ? ;
// Less data transferred from disk
Typed operations
Use typed methods to avoid JSON parsing overhead.
use serde :: { Serialize , Deserialize };
#[derive( Serialize , Deserialize )]
struct User {
name : String ,
email : String ,
}
// Faster: direct deserialization
let user : Option < User > = users . find_by_id_typed ( "user_123" ) ? ;
// Slower: JSON Value then application-level parsing
let user_value = users . find_by_id ( "user_123" ) ? ;
let user : User = serde_json :: from_value ( user_value ) ? ;
Transaction optimization
Minimize transaction scope
Keep transactions short and focused.
Good: Short transaction
Bad: Long-lived transaction
let mut tx = db . begin () ? ;
let users = tx . collection ( "users" );
users . insert ( json! ({ "name" : "Alice" })) ? ;
tx . commit () ? ; // Fast commit
Use retryable transactions
For automatic conflict resolution.
use jasonisnthappy :: TransactionConfig ;
// Configure retries
db . set_transaction_config ( TransactionConfig {
max_retries : 5 ,
retry_backoff_base_ms : 1 ,
max_retry_backoff_ms : 100 ,
});
// Run with automatic retry
let result = db . run_transaction ( | tx | {
let users = tx . collection ( "users" );
let count = users . count () ? ;
users . insert ( json! ({ "count" : count })) ? ;
Ok ( count )
}) ? ;
MVCC benefits
Reads never block writes, writes never block reads.
use std :: thread;
// Reader thread (never blocked)
let db_clone = db . clone ();
let reader = thread :: spawn ( move || {
let users = db_clone . collection ( "users" );
loop {
let count = users . count () . unwrap ();
println! ( "Count: {}" , count );
thread :: sleep ( Duration :: from_millis ( 10 ));
}
});
// Writer thread (runs concurrently)
let db_clone = db . clone ();
let writer = thread :: spawn ( move || {
let users = db_clone . collection ( "users" );
loop {
users . insert ( json! ({ "data" : "test" })) . unwrap ();
thread :: sleep ( Duration :: from_millis ( 100 ));
}
});
// Both threads run concurrently without blocking
Memory optimization
Page cache
Configure the page cache size.
use jasonisnthappy :: DatabaseOptions ;
let db = Database :: open_with_options ( "my.db" , DatabaseOptions {
cache_size : 50_000 , // 50K pages = ~200MB
.. Default :: default ()
}) ? ;
Cache sizing guide:
Small DBs (< 100MB): 10,000 pages (~40MB)
Medium DBs (< 1GB): 25,000 pages (~100MB)
Large DBs (> 1GB): 50,000+ pages (~200MB+)
Limit result sets
Use pagination to avoid loading large result sets.
// Good: Paginate large result sets
let page_size = 100 ;
let results = users . query ()
. filter ( "status is \" active \" " )
. limit ( page_size )
. execute () ? ;
// Bad: Load all results into memory
let all_results = users . find ( "status is \" active \" " ) ? ; // Could be millions
Garbage collection
Reclaim space from old MVCC versions.
// Periodically clean up old versions
let stats = db . garbage_collect () ? ;
println! ( "Versions removed: {}" , stats . versions_removed);
println! ( "Pages freed: {}" , stats . pages_freed);
println! ( "Bytes freed: {}" , stats . bytes_freed);
Garbage collection is safe to run while the database is in use. It only removes versions no longer visible to any transaction.
Disk I/O optimization
SSD vs HDD
Jasonisnthappy performs best on SSDs.
Storage Random reads Sequential writes Recommended SSD Excellent Excellent ✅ Yes NVMe SSD Exceptional Exceptional ✅ Best HDD Poor Good ⚠️ Limited
File placement
Separate database and WAL on different disks (advanced).
// Database on fast SSD
let db = Database :: open ( "/mnt/ssd/app.db" ) ? ;
// WAL on separate disk (if supported)
// Note: Current implementation keeps WAL with database
Batch commits
Jasonisnthappy batches commits automatically for better throughput.
// Multiple concurrent writers are batched
let threads : Vec < _ > = ( 0 .. 4 )
. map ( | i | {
let db = db . clone ();
thread :: spawn ( move || {
let users = db . collection ( "users" );
users . insert ( json! ({ "thread" : i })) . unwrap ();
})
})
. collect ();
// Commits are batched together for efficiency
Benchmarking
Running benchmarks
# Run all benchmarks
cargo run --release --example bench_all
# Results show:
# - Write throughput
# - Read latency
# - Bulk insert performance
# - Concurrent operations
Custom benchmarks
use std :: time :: Instant ;
let db = Database :: open ( "bench.db" ) ? ;
let users = db . collection ( "users" );
// Benchmark inserts
let start = Instant :: now ();
for i in 0 .. 1000 {
users . insert ( json! ({ "id" : i })) ? ;
}
let elapsed = start . elapsed ();
println! ( "1000 inserts: {:.2?}" , elapsed );
println! ( "Throughput: {:.0} ops/sec" , 1000.0 / elapsed . as_secs_f64 ());
// Benchmark queries
let start = Instant :: now ();
for i in 0 .. 1000 {
users . find_one ( & format! ( "id is {}" , i )) ? ;
}
let elapsed = start . elapsed ();
println! ( "1000 queries: {:.2?}" , elapsed );
println! ( "Avg latency: {:.2}ms" , elapsed . as_millis () as f64 / 1000.0 );
Monitoring
Metrics
Track database performance with built-in metrics.
use jasonisnthappy :: Database ;
let db = Database :: open ( "my.db" ) ? ;
// Get metrics snapshot
let metrics = db . metrics ();
println! ( "Transactions:" );
println! ( " Begun: {}" , metrics . transactions_begun);
println! ( " Committed: {}" , metrics . transactions_committed);
println! ( " Rolled back: {}" , metrics . transactions_rolled_back);
println! ( " Conflicts: {}" , metrics . transaction_conflicts);
println! ( " \n Cache:" );
println! ( " Hits: {}" , metrics . cache_hits);
println! ( " Misses: {}" , metrics . cache_misses);
let hit_rate = metrics . cache_hits as f64 /
( metrics . cache_hits + metrics . cache_misses) as f64 * 100.0 ;
println! ( " Hit rate: {:.1}%" , hit_rate );
println! ( " \n WAL:" );
println! ( " Frames written: {}" , metrics . wal_frames_written);
println! ( " Checkpoints: {}" , metrics . checkpoints);
Use metrics to identify bottlenecks.
let metrics = db . metrics ();
let hit_rate = metrics . cache_hits as f64 /
( metrics . cache_hits + metrics . cache_misses) as f64 ;
if hit_rate < 0.9 {
println! ( "Cache too small - increase cache_size" );
}
Monitor transaction conflicts
if metrics . transaction_conflicts > metrics . transactions_committed / 10 {
println! ( "High conflict rate - review transaction patterns" );
}
let frame_count = db . frame_count ();
if frame_count > 10000 {
println! ( "Large WAL - consider checkpoint" );
db . checkpoint () ? ;
}
Best practices summary
Do:
Use insert_many for bulk inserts (100-1000 docs)
Create indexes on frequently queried fields
Use find_one when you only need the first result
Project only needed fields
Keep transactions short
Use typed operations for hot paths
Configure adequate cache size
Run garbage collection periodically
Avoid:
Individual inserts in loops
Queries without indexes on large collections
Loading entire collections with find_all
Long-running transactions
Excessive checkpoint frequency
Too many indexes (slow writes)
Running on slow HDDs if possible
E-commerce application
// Product catalog: 100,000 products
// - Indexed: name, category, price
// - Cache: 50,000 pages (~200MB)
// - Storage: NVMe SSD
// Search products: 0.5-2ms
let results = products . query ()
. filter ( "category is \" electronics \" and price < 500" )
. sort_by ( "price" , SortOrder :: Asc )
. limit ( 20 )
. execute () ? ;
// Add to cart: 8-12ms (with ACID)
let cart = db . collection ( "carts" );
cart . insert ( json! ({
"user_id" : user_id ,
"product_id" : product_id ,
"quantity" : 1
})) ? ;
// Checkout (bulk write): 30-50ms
let result = db . run_transaction ( | tx | {
// Update inventory, create order, clear cart
// ... multiple operations ...
Ok ( order_id )
}) ? ;
Analytics dashboard
// Events: 1M+ documents
// - Aggregation: 100-500ms
// - Cached results: < 1ms
let hourly_stats = events . aggregate ()
. match_ ( "timestamp > 1704067200" )
. group_by ( "event_type" )
. count ( "total" )
. execute () ? ; // ~200ms for 1M events
Next steps
Indexes Create indexes to speed up queries
Querying Optimize query patterns
CRUD operations Use efficient write operations
Backup and restore Backup strategies for production