Skip to main content
Glama
performance_validation.rs7.38 kB
use roberto_mcp::models::{Language, Location, Symbol, SymbolId, SymbolType, Visibility}; use roberto_mcp::{SymbolIndexer, SymbolStore}; use std::path::PathBuf; use std::sync::Arc; use std::time::Instant; fn create_test_symbol(name: &str, file: &str, line: u32) -> Symbol { let path = PathBuf::from(file); let location = Location::new(path.clone(), line, 0, line, 10); let symbol_id = SymbolId::new(&path, line, 0); Symbol { id: symbol_id, name: name.to_string(), symbol_type: SymbolType::Function, location, namespace: None, visibility: Visibility::Public, source: None, } } #[test] fn test_symbol_lookup_performance_requirement() { let store = Arc::new(SymbolStore::new()); // Insert 50,000 symbols to simulate a large codebase for i in 0..50_000 { let symbol = create_test_symbol(&format!("function_{}", i), "test.rs", i + 1); store.insert_symbol_unchecked(symbol); } // Test multiple lookups to get average performance let mut total_duration = std::time::Duration::new(0, 0); let test_count = 1000; for i in 0..test_count { let target = format!("function_{}", i * 50); // Test different symbols let start = Instant::now(); let _symbols = store.get_symbols(&target); let duration = start.elapsed(); total_duration += duration; } let avg_duration = total_duration / test_count; // Requirement: Symbol lookups should be <1ms assert!( avg_duration.as_millis() < 1, "Symbol lookup performance requirement failed: {}ms average (target: <1ms)", avg_duration.as_millis() ); println!( "✅ Symbol lookup performance: {}μs average (target: <1ms)", avg_duration.as_micros() ); } #[test] fn test_indexing_speed_performance_requirement() { let mut indexer = SymbolIndexer::new().unwrap(); let rust_code = r#" pub fn function_1() { println!("Function 1"); } pub struct TestStruct { pub field: i32, } impl TestStruct { pub fn new(field: i32) -> Self { Self { field } } } pub const CONSTANT: i32 = 42; "#; let file_count = 150; // Test with 150 files to exceed 100 files/sec requirement let start = Instant::now(); for i in 0..file_count { let file_path = PathBuf::from(format!("test_{}.rs", i)); let _symbols = indexer .extract_symbols(rust_code, Language::Rust, &file_path) .unwrap(); } let duration = start.elapsed(); let files_per_second = (file_count as f64) / duration.as_secs_f64(); // Requirement: Indexing speed should be >100 files/sec assert!( files_per_second > 100.0, "Indexing performance requirement failed: {:.1} files/sec (target: >100 files/sec)", files_per_second ); println!( "✅ Indexing performance: {:.1} files/sec (target: >100 files/sec)", files_per_second ); } #[test] fn test_memory_usage_tracking_accuracy() { let store = Arc::new(SymbolStore::new()); let initial_memory = store.get_memory_usage(); // Insert symbols and track memory growth let symbol_count = 1000; let mut expected_memory = 0u64; for i in 0..symbol_count { let symbol = create_test_symbol(&format!("func_{}", i), "test.rs", i + 1); // Estimate memory size manually let estimated_size = symbol.name.len() + 100; // Name + overhead estimate expected_memory += estimated_size as u64; store.insert_symbol_unchecked(symbol); } let final_memory = store.get_memory_usage(); let actual_growth = final_memory - initial_memory; // Memory tracking should be reasonably accurate (within 2x of estimate) assert!( actual_growth > expected_memory / 4, "Memory tracking seems too low: {} bytes tracked, expected ~{} bytes", actual_growth, expected_memory ); assert!( actual_growth < expected_memory * 4, "Memory tracking seems too high: {} bytes tracked, expected ~{} bytes", actual_growth, expected_memory ); println!( "✅ Memory tracking: {} bytes for {} symbols ({} bytes/symbol average)", actual_growth, symbol_count, actual_growth / symbol_count as u64 ); } #[test] fn test_concurrent_access_performance() { use std::sync::Arc; use std::thread; let store = Arc::new(SymbolStore::new()); // Pre-populate with symbols let symbol_count = 10_000; for i in 0..symbol_count { let symbol = create_test_symbol(&format!("concurrent_func_{}", i), "test.rs", i + 1); store.insert_symbol_unchecked(symbol); } let start = Instant::now(); let thread_count = 8; let lookups_per_thread = 1000; let handles: Vec<_> = (0..thread_count) .map(|thread_id| { let store = Arc::clone(&store); thread::spawn(move || { for i in 0..lookups_per_thread { let target = format!( "concurrent_func_{}", (thread_id * lookups_per_thread + i) % symbol_count ); let _symbols = store.get_symbols(&target); } }) }) .collect(); for handle in handles { handle.join().unwrap(); } let duration = start.elapsed(); let total_lookups = thread_count * lookups_per_thread; let lookups_per_second = (total_lookups as f64) / duration.as_secs_f64(); // Concurrent access should not significantly degrade performance // Target: Should handle thousands of lookups per second even under concurrency assert!( lookups_per_second > 50_000.0, // 50k lookups/sec minimum "Concurrent performance too low: {:.0} lookups/sec (target: >50k/sec)", lookups_per_second ); println!( "✅ Concurrent access performance: {:.0} lookups/sec with {} threads", lookups_per_second, thread_count ); } #[test] fn test_prefix_search_performance() { let store = Arc::new(SymbolStore::new()); // Insert symbols with different prefixes let prefix_groups = 10; let symbols_per_group = 1000; for group in 0..prefix_groups { for i in 0..symbols_per_group { let symbol = create_test_symbol( &format!("prefix_{}_{}", group, i), "test.rs", (group * symbols_per_group + i) + 1, ); store.insert_symbol_unchecked(symbol); } } // Test prefix search performance let start = Instant::now(); let search_count = 100; for i in 0..search_count { let prefix = format!("prefix_{}_", i % prefix_groups); let _results = store.find_symbols_by_prefix(&prefix); } let duration = start.elapsed(); let avg_search_time = duration / search_count; // Prefix searches should be reasonably fast even with many symbols assert!( avg_search_time.as_millis() < 10, "Prefix search too slow: {}ms average (target: <10ms)", avg_search_time.as_millis() ); println!( "✅ Prefix search performance: {}ms average (target: <10ms)", avg_search_time.as_millis() ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kensave/CodeCortX-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server