Skip to content

Performance Improvement: Implement batched config writes #45

Description

@coderabbitai

Overview

Currently, each config update triggers an immediate file write operation. This can lead to performance issues if configs are updated frequently, as it creates unnecessary I/O overhead.

Proposed Solution

Implement a batching mechanism for config writes that:

  • Tracks 'dirty' configs that need to be saved
  • Uses a scheduler to automatically save changes periodically (e.g., every 5 seconds)
  • Provides methods to force immediate saves when needed
  • Cleans up resources on shutdown

Implementation Example

public class ConfigManager {
    // Add these fields
    private final Map<String, Long> lastWriteTime = new HashMap<>();
    private final Map<String, Boolean> dirtyConfigs = new HashMap<>();
    private static final long WRITE_DELAY_MS = 5000; // 5 seconds between writes
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    
    // Constructor - add this line at the end
    public ConfigManager(String botName, JDA jda) {
        // existing code...
        scheduler.scheduleAtFixedRate(this::flushDirtyConfigs, WRITE_DELAY_MS, WRITE_DELAY_MS, TimeUnit.MILLISECONDS);
    }
    
    // Modify setConfig method
    public void setConfig(String serverId, Config config) {
        configs.put(serverId, config);
        markDirty(serverId);
    }
    
    // Modify setValue method
    public void setValue(String serverId, String key, Object value) {
        Config config = configs.getOrDefault(serverId, configs.get("default"));
        config.put(key, value);
        markDirty(serverId);
    }
    
    // New helper methods
    private void markDirty(String serverId) {
        dirtyConfigs.put(serverId, true);
    }
    
    private void flushDirtyConfigs() {
        dirtyConfigs.entrySet().removeIf(entry -> {
            if (entry.getValue()) {
                writeConfigToFile(entry.getKey(), configs.get(entry.getKey()));
                return true;
            }
            return false;
        });
    }
    
    // Add this method for explicit saves
    public void saveNow(String serverId) {
        if (configs.containsKey(serverId)) {
            writeConfigToFile(serverId, configs.get(serverId));
            dirtyConfigs.remove(serverId);
        }
    }
    
    // Add this to save all pending changes
    public void saveAllNow() {
        configs.keySet().forEach(this::saveNow);
    }
    
    // Don't forget to add this to clean up resources
    public void shutdown() {
        scheduler.shutdown();
        saveAllNow();
    }
}

Reference

This issue was created based on a discussion in PR #41: #41 (comment)

Benefits

  • Reduced I/O operations
  • Better performance for frequent config updates
  • Clean shutdown handling

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions