- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
4.2 KiB
4.2 KiB
Testing Performance Optimizations
This document outlines the performance optimizations implemented to improve test execution speed in the Rustelo server.
Performance Issues Identified
Before Optimizations
- Total test execution time: ~30 seconds (parallel) / ~60 seconds (sequential)
- 155 tests with various expensive operations
- Primary bottlenecks: Password hashing and syntax highlighting initialization
Root Causes
-
Password Hashing (Argon2)
- Each
PasswordService::new()call used production-grade Argon2 parameters - Intentionally slow for security (~100-500ms per hash operation)
- Multiple tests calling password hashing functions
- Each
-
Syntax Highlighting (Syntect)
- Each
ContentRenderer::new()call loaded entire syntax highlighting datasets SyntaxSet::load_defaults_newlines()andThemeSet::load_defaults()are expensive- 6+ content renderer tests each creating new instances
- Each
-
Cumulative Effect
- Many tests performing file I/O, database operations, template rendering
- Even with parallel execution, slowest operations bottleneck the suite
Optimizations Implemented
1. Fast Password Hashing for Tests
File: server/src/auth/password.rs
/// Create a PasswordService with faster parameters for testing
#[cfg(test)]
pub fn new_for_testing() -> Self {
// Use minimal but valid parameters for faster testing
let params = Params::new(1024, 1, 1, None).unwrap(); // 1KB memory, 1 iteration, 1 thread
let argon2 = Argon2::new(argon2::Algorithm::Argon2id, argon2::Version::V0x13, params);
Self { argon2 }
}
Impact: Password hashing tests now complete in milliseconds instead of seconds.
2. Lightweight Content Renderer for Tests
File: server/src/content/renderer.rs
/// Create a lightweight ContentRenderer for testing without expensive syntax highlighting
#[cfg(test)]
pub fn new_for_testing() -> Self {
Self {
syntax_set: SyntaxSet::new(),
theme_set: ThemeSet::new(),
theme_name: "base16-ocean.dark".to_string(),
enable_syntax_highlighting: false,
enable_tables: true,
enable_strikethrough: true,
enable_tasklists: true,
enable_footnotes: true,
enable_smart_punctuation: true,
custom_css_classes: HashMap::new(),
}
}
Impact: Content renderer tests finish in <0.01s instead of 0.04s.
3. Test Configuration Fixes
File: server/tests/config_integration_test.rs
Fixed configuration parsing issues that were causing test failures:
- Added missing
providerfield to email configurations - Fixed
csrfdefault value assertion (true vs false) - Updated features configuration to use proper nested TOML structure
Performance Results
After Optimizations
- Configuration tests: All 7 tests passing
- Password hashing tests: ~0.03s (down from several seconds)
- Content renderer tests: ~0.00s (down from 0.04s)
- Overall test suite: Still ~30s due to other operations
Parallel vs Sequential Execution
- Parallel (default): ~30 seconds
- Sequential (
RUST_TEST_THREADS=1): ~60 seconds - Parallelization efficiency: ~50% reduction in total time
Remaining Performance Considerations
While significant improvements were made, the test suite still takes ~30 seconds due to:
- Template rendering and file I/O operations
- Database operations (SQLite migrations)
- Configuration loading and validation
- Cumulative effect of 155 tests
Best Practices for Future Tests
- Use test-optimized constructors when available (
new_for_testing()) - Mock expensive operations where possible
- Use faster algorithms for cryptographic operations in tests
- Share expensive resources between tests when safe
- Consider using
lazy_static!for expensive one-time initializations
Recommendations for Further Optimization
- Mock database operations with in-memory alternatives
- Cache template loading across tests
- Use test-specific configuration with minimal features enabled
- Profile individual tests to identify remaining bottlenecks
- Consider splitting large test suites into smaller, focused modules
Last updated: Test performance optimizations completed