AdvancedPerformanceIntelligent Caching

Intelligent Caching System

Lokus v1.3.4 introduced a sophisticated intelligent caching system that dramatically improves performance by eliminating redundant file system operations.

The Intelligent Caching System was introduced in v1.3.4 (PR #242) and provides 85-90% reduction in file system calls.

Overview

The caching system implements a 5-minute Time-To-Live (TTL) cache that stores workspace file listings in memory, eliminating the need for repeated file system scans during normal operation.

Performance Impact

Real-world performance improvements in v1.3.4:

OperationBefore (v1.3.3)After (v1.3.4)Improvement
Command Palette (first open)~200-400ms~200-400msBaseline
Command Palette (subsequent)~200-400msInstant~95% faster
Split View (same file)~400ms~200ms50% faster
Split View (different file)~400ms~200ms50% faster
Bases View (reopen)Full scanCached90% faster
Tab SwitchingReloadsCachedInstant

Overall Result: Most file operations become instant after initial load, dramatically improving the user experience during normal workflows.

How It Works

Cache Architecture

The caching system operates at multiple levels:

1. BasesDataManager Cache

Location: src/bases/data/index.js

class BasesDataManager {
  constructor(options = {}) {
    this.fileListCache = null;           // Cache storage
    this.fileListCacheTime = 0;          // Timestamp of cache
    this.options = {
      cacheTimeout: 5 * 60 * 1000,       // 5 minutes in milliseconds
      ...options
    };
  }
 
  async getAllFiles() {
    // Check cache first (5 minute TTL)
    const now = Date.now();
    const cacheAge = now - this.fileListCacheTime;
 
    if (this.fileListCache && cacheAge < this.options.cacheTimeout) {
      console.log('📋 Cache hit! Using cached file list');
      return this.fileListCache;
    }
 
    console.log('🔄 Cache miss or expired, loading from backend...');
 
    // Fetch from backend
    const files = await invoke('read_workspace_files', {
      workspacePath: this.workspacePath
    });
 
    // Cache the results
    this.fileListCache = processedFiles;
    this.fileListCacheTime = now;
 
    return processedFiles;
  }
}

2. Command Palette Optimization

Location: src/components/CommandPalette.jsx

Before (v1.3.3): Loaded files on every open and fileTree change

After (v1.3.4): Only loads if cache is empty

// Load files only if not already cached
useEffect(() => {
  if (basesFiles.length === 0) {
    // Cache miss - load from backend
    loadFiles();
  } else {
    console.log('📋 Using cached basesFiles for command palette');
  }
}, []); // Removed fileTree from dependencies

3. Split View Optimization

Result: Reuses cached data when opening split views, eliminating duplicate file system calls.

Cache Lifecycle

  1. Initial Load: First file operation triggers backend scan and caches results
  2. Cache Hit: Subsequent operations use cached data (instant response)
  3. TTL Expiration: After 5 minutes, cache expires
  4. Refresh: Next operation triggers fresh backend scan and updates cache
  5. Repeat: Cycle continues for optimal balance of freshness and performance

Benefits

1. Reduced File System I/O

  • 70-80% reduction in read_workspace_files backend calls
  • 90% reduction in duplicate file system operations
  • Lower disk I/O improves battery life on laptops
  • Reduced wear on SSDs

2. Instant Response Times

After initial load, operations become effectively instant:

  • Command Palette: Opens immediately (no delay)
  • File Browser: Instant file list population
  • Bases View: Immediate display of data
  • Tab Operations: No reload delays

3. Better User Experience

  • Snappy Interface: Operations feel instantaneous
  • Smooth Workflow: No interruptions from loading delays
  • Predictable Performance: Consistent speed after warm-up
  • Reduced Frustration: No more waiting for repetitive operations

4. Resource Efficiency

  • Lower CPU Usage: Fewer file system operations
  • Reduced Memory Allocations: Reuse existing data structures
  • Better Battery Life: Less disk I/O on laptops
  • Cooler Operation: Reduced CPU usage means less heat

Cache Strategies

Time-To-Live (TTL) Cache

What It Is: Data is cached for a fixed duration (5 minutes), then expires.

Why 5 Minutes:

  • Balance: Fresh enough for most workflows, long enough for significant benefit
  • File Changes: Most users don’t add/remove files every few minutes
  • Memory: Reasonable memory footprint for typical workspaces
  • Predictable: Consistent behavior across sessions

Trade-offs:

  • Stale Data: New files added externally won’t appear for up to 5 minutes
  • Memory Usage: Cache occupies memory (negligible for most workspaces)
  • Complexity: Additional cache management logic

Cache Invalidation

The cache automatically invalidates (clears) in these scenarios:

  1. TTL Expiration: After 5 minutes, cache is considered stale
  2. Explicit Reload: User-triggered workspace refresh
  3. Workspace Change: Switching to different workspace
  4. App Restart: Cache doesn’t persist across sessions (by design)
💡

Note: File changes made within Lokus automatically update the cache, so you’ll always see your own changes immediately.

What’s Cached

Cached Data:

  • File paths and names
  • File metadata (size, dates, extensions)
  • Directory structure
  • Basic file properties

Not Cached:

  • File contents (loaded on-demand)
  • Frontmatter (parsed when needed)
  • Full property indexes (computed separately)

Performance Monitoring

Console Logging

Cache operations are logged to the console for debugging:

// Cache hit
📋 Cache hit! Using cached file list
 
// Cache miss
🔄 Cache miss or expired, loading from backend...
 
// Command palette cache
📋 Using cached basesFiles for command palette
 
// Bases cache status
📋 Cache hits in BasesDataManager

Open Developer Console (⌘+Shift+I on macOS, F12 on Windows/Linux) to monitor cache behavior.

Performance Testing

To verify cache improvements:

  1. First Open: Open Command Palette (⌘+K) - note delay
  2. Second Open: Open again immediately - should be instant
  3. Bases View: Open Bases, close, reopen - second time is instant
  4. Split View: Open split view multiple times - faster each time
  5. Check Console: Look for cache hit messages

Measuring Performance

// Measure command palette open time
const start = performance.now();
// Open command palette
const end = performance.now();
console.log(`Command palette opened in ${end - start}ms`);
 
// First time: ~200-400ms
// Second time: <10ms (instant)

Optimization Tips

Maximize Cache Benefits

  1. Keep Workspace Open: Don’t restart Lokus unnecessarily
  2. Work Continuously: Cache remains hot during active use
  3. Batch File Operations: Add multiple files at once to minimize reloads
  4. Use Internal Operations: File operations in Lokus update cache immediately

Large Workspaces

For workspaces with 1,000+ files:

  • Initial cache load may take longer (one-time cost)
  • Cache provides even greater benefits (more files = more savings)
  • Consider using Bases source folders to limit scope
  • Add exclude patterns for node_modules, .git, etc.

Memory Considerations

Cache memory usage is minimal:

  • Small Workspace (100 files): ~10KB
  • Medium Workspace (1,000 files): ~100KB
  • Large Workspace (10,000 files): ~1MB
  • Expiration: Cache clears after 5 minutes of inactivity
💡

Even for very large workspaces, cache memory overhead is negligible compared to the performance benefits.

Advanced Configuration

Adjusting Cache Timeout

For advanced users, cache timeout can be configured:

// In BasesDataManager initialization
const manager = new BasesDataManager({
  cacheTimeout: 10 * 60 * 1000  // 10 minutes
});
 
// Shorter for rapidly changing workspaces
const manager = new BasesDataManager({
  cacheTimeout: 2 * 60 * 1000   // 2 minutes
});

Disabling Cache

For testing or troubleshooting:

// Set timeout to 0 to effectively disable caching
const manager = new BasesDataManager({
  cacheTimeout: 0  // No caching, always fresh
});

Manual Cache Control

Programmatic cache management:

// Clear cache manually
basesDataManager.fileListCache = null;
basesDataManager.fileListCacheTime = 0;
 
// Force refresh
await basesDataManager.getAllFiles(); // Bypasses cache
 
// Check cache age
const age = Date.now() - basesDataManager.fileListCacheTime;
console.log(`Cache age: ${age}ms`);

Troubleshooting

Cache Not Working

Symptoms: Operations still slow after first use

Solutions:

  1. Check Console: Look for cache hit messages
  2. Verify Version: Ensure you’re on v1.3.4 or later
  3. Check Configuration: Verify cacheTimeout is set
  4. Restart App: Clear any state issues
  5. Check Workspace: Ensure workspace is properly initialized

Stale Data

Symptoms: New external files don’t appear

Reasons:

  • Files added outside Lokus (other apps, terminal)
  • Cache hasn’t expired yet (< 5 minutes)

Solutions:

  1. Wait 5 Minutes: Cache will auto-refresh
  2. Reload Workspace: Use workspace reload command
  3. Restart Lokus: Clears cache immediately
  4. Use Lokus: Create files in Lokus to auto-update cache

Excessive Memory Usage

Symptoms: Lokus using too much memory

Unlikely Cause: Cache is minimal (< 1MB even for large workspaces)

Real Causes:

  • Many open tabs (each loads full content)
  • Large images in notes
  • Graph view with thousands of nodes
  • Memory leak (unrelated to cache)

Solutions:

  1. Close unused tabs
  2. Optimize image sizes
  3. Limit graph view scope
  4. Restart Lokus periodically

Best Practices

For Users

  • Let It Cache: Give operations a moment to complete first time
  • Reuse Operations: Benefit from cache by repeating operations
  • Don’t Restart Unnecessarily: Cache is lost on restart
  • Monitor Performance: Check console to verify cache hits

For Developers

  • Respect Cache: Don’t bypass cache unless necessary
  • Update Cache: When modifying files, update cache
  • Document Changes: Note cache-affecting code changes
  • Test Both Paths: Test cache hits and misses
  • Profile Performance: Measure improvements quantitatively

For Plugin Developers

If you’re developing plugins:

// Access cache through BasesDataManager
const manager = basesDataManager;
const files = await manager.getAllFiles(); // Uses cache
 
// Force refresh if needed
manager.fileListCache = null;
const freshFiles = await manager.getAllFiles();
 
// Check if cache is valid
const isCacheValid = manager.fileListCache &&
  (Date.now() - manager.fileListCacheTime) < manager.options.cacheTimeout;

Backward Compatibility

The caching system is fully backward compatible:

  • No API Changes: Existing code continues to work
  • Progressive Enhancement: Automatically faster without code changes
  • Graceful Degradation: Falls back to direct load if cache unavailable
  • Configuration Optional: Works with default settings

Future Enhancements

Planned improvements for the caching system:

  • Smart Invalidation: Detect file system changes and invalidate automatically
  • Persistent Cache: Cache survives app restarts (with validation)
  • Tiered Caching: Multiple cache layers for different data types
  • Cache Preloading: Predictively load likely-needed data
  • Compression: Compress cached data for larger workspaces
  • Statistics: Cache hit rate and performance metrics dashboard

The caching system complements other performance features:


Impact Summary: The intelligent caching system represents one of the most significant performance improvements in Lokus history, making the app feel dramatically faster during everyday use without any user configuration required.