codex-memory 3.0.15

A simple memory storage service with MCP interface for Claude Desktop
Documentation
// Performance test entry point
mod common;
mod performance;

// Import performance benchmarks for database optimizations
use common::test_db_manager::TestDatabaseManager;
use codex_memory::storage::Storage;
use std::time::Instant;

#[tokio::test]
async fn benchmark_row_mapping_performance() -> Result<(), Box<dyn std::error::Error>> {
    let mut manager = TestDatabaseManager::new()?;
    let pool = manager.setup_test_database().await?;
    let storage = Storage::new(pool);

    // Insert test data
    let mut memory_ids = Vec::new();
    let start = Instant::now();
    
    for i in 0..100 { // Reduced for CI performance
        let id = storage.store(
            &format!("Test content {}", i),
            format!("Test context {}", i),
            format!("Test summary {}", i),
            Some(vec![format!("tag{}", i)]),
        ).await?;
        memory_ids.push(id);
    }
    
    let insert_duration = start.elapsed();
    println!("✅ Inserted 100 memories in: {:?}", insert_duration);

    // Benchmark get operations (using sqlx::FromRow optimization)
    let start = Instant::now();
    
    for &id in &memory_ids[..50] { // Test first 50
        let _memory = storage.get(id).await?;
    }
    
    let get_duration = start.elapsed();
    println!("✅ Retrieved 50 memories in: {:?}", get_duration);
    println!("✅ Average get time: {:?}", get_duration / 50);

    // Target: <2ms per get operation (significant improvement from manual mapping)
    assert!(get_duration / 50 < std::time::Duration::from_millis(2), 
           "Get operation too slow: {:?}", get_duration / 50);

    manager.cleanup().await?;
    Ok(())
}

#[tokio::test]
async fn benchmark_connection_pool_utilization() -> Result<(), Box<dyn std::error::Error>> {
    let mut manager = TestDatabaseManager::new()?;
    let pool = manager.setup_test_database().await?;
    let storage = Storage::new(pool.clone());

    println!("✅ Connection pool optimized config:");
    println!("  Pool configuration optimized for production load");
    
    // Note: In sqlx 0.8, pool options are not directly readable from the pool
    // Our configuration in database/core.rs sets max_connections(50) and min_connections(2)

    // Simulate concurrent operations (scaled down for CI)
    let start = Instant::now();
    
    let mut handles = Vec::new();
    for i in 0..20 { // Reduced concurrent load for CI
        let storage_clone = Storage::new(pool.clone());
        let handle = tokio::spawn(async move {
            let content = format!("Concurrent content {}", i);
            storage_clone.store(
                &content,
                "Concurrent context".to_string(),
                "Concurrent summary".to_string(),
                Some(vec!["concurrent".to_string()]),
            ).await
        });
        handles.push(handle);
    }

    let mut results = Vec::new();
    for handle in handles {
        results.push(handle.await??);
    }

    let concurrent_duration = start.elapsed();
    println!("✅ Completed 20 concurrent operations in: {:?}", concurrent_duration);
    println!("✅ Average operation time: {:?}", concurrent_duration / 20);
    
    // Target: <100ms per concurrent operation on average
    assert!(concurrent_duration / 20 < std::time::Duration::from_millis(100),
           "Concurrent operations too slow: {:?}", concurrent_duration / 20);

    manager.cleanup().await?;
    Ok(())
}