devflow-ai
Version:
Enterprise-grade AI agent orchestration with swarm management UI dashboard
299 lines (233 loc) • 7.35 kB
Markdown
# Swarm Optimization Migration Guide
## Overview
This guide helps you migrate the existing swarm system to use the new optimizations, achieving the targeted 2.5x performance improvement.
## Phase 1: Quick Wins (Week 1)
### 1. Replace Synchronous Execution
**Before:**
```typescript
// In SwarmExecutor
async executeTask(task: Task) {
const result = await claudeAPI.call(task); // Blocking
await fs.writeFile(outputPath, result); // Blocking
return result;
}
```
**After:**
```typescript
// Import optimizations
import { OptimizedExecutor } from './optimizations/index.ts';
// Initialize once
const executor = new OptimizedExecutor({
connectionPool: { min: 2, max: 10 },
concurrency: 10,
caching: { enabled: true, ttl: 3600000 },
fileOperations: { outputDir: './outputs' }
});
// Use in SwarmExecutor
async executeTask(task: TaskDefinition, agentId: AgentId) {
return await executor.executeTask(task, agentId);
}
```
### 2. Fix Memory Leaks
**Before:**
```typescript
// In SwarmCoordinator
private eventHistory: Event[] = []; // Unbounded
private taskStates: Map<string, TaskState> = new Map(); // Never cleaned
handleEvent(event: Event) {
this.eventHistory.push(event); // Memory leak
}
```
**After:**
```typescript
import { CircularBuffer, TTLMap } from './optimizations/index.ts';
// In SwarmCoordinator
private eventHistory = new CircularBuffer<SwarmEvent>(1000); // Max 1000 events
private taskStates = new TTLMap<string, TaskDefinition>({
defaultTTL: 3600000, // 1 hour TTL
maxSize: 10000 // Max 10k tasks
});
handleEvent(event: SwarmEvent) {
this.eventHistory.push(event); // Automatic rotation
}
// For task cleanup
completeTask(taskId: string) {
// Task will auto-expire from TTLMap after 1 hour
const task = this.taskStates.get(taskId);
if (task) {
task.status = 'completed';
// No need to manually delete - TTL handles it
}
}
```
### 3. Update File Operations
**Before:**
```typescript
import { promises as fs } from 'fs';
async saveResult(path: string, data: any) {
await fs.writeFile(path, JSON.stringify(data));
}
```
**After:**
```typescript
import { AsyncFileManager } from './optimizations/index.ts';
const fileManager = new AsyncFileManager();
async saveResult(path: string, data: any) {
await fileManager.writeJSON(path, data); // Non-blocking with queue
}
```
## Phase 2: Agent Selection Optimization
### Current O(n²) Selection
```typescript
// In SwarmCoordinator
private selectAgent(task: TaskDefinition): AgentState | null {
for (const agent of this.agents.values()) {
for (const capability of agent.capabilities) {
if (task.requirements?.includes(capability)) {
return agent;
}
}
}
return null;
}
```
### Optimized O(1) Selection
```typescript
// Add to SwarmCoordinator
private agentCapabilityIndex = new Map<string, Set<string>>(); // capability -> agent IDs
private agentSelectionCache = new TTLMap<string, string>({ maxSize: 1000 });
// Build index when agents are added
private indexAgent(agent: AgentState) {
for (const capability of agent.capabilities) {
if (!this.agentCapabilityIndex.has(capability)) {
this.agentCapabilityIndex.set(capability, new Set());
}
this.agentCapabilityIndex.get(capability)!.add(agent.id.id);
}
}
// Optimized selection
private selectAgent(task: TaskDefinition): AgentState | null {
const cacheKey = `${task.type}-${task.requirements?.join(',')}`;
// Check cache
const cachedAgentId = this.agentSelectionCache.get(cacheKey);
if (cachedAgentId) {
const agent = this.agents.get(cachedAgentId);
if (agent?.status === 'idle') return agent;
}
// Find eligible agents using index
if (!task.requirements?.length) return null;
const eligibleAgentIds = new Set<string>();
for (const requirement of task.requirements) {
const agentsWithCapability = this.agentCapabilityIndex.get(requirement);
if (!agentsWithCapability) return null;
if (eligibleAgentIds.size === 0) {
agentsWithCapability.forEach(id => eligibleAgentIds.add(id));
} else {
// Keep only agents that have all requirements
for (const id of eligibleAgentIds) {
if (!agentsWithCapability.has(id)) {
eligibleAgentIds.delete(id);
}
}
}
}
// Select best available agent
for (const agentId of eligibleAgentIds) {
const agent = this.agents.get(agentId);
if (agent?.status === 'idle') {
this.agentSelectionCache.set(cacheKey, agentId);
return agent;
}
}
return null;
}
```
## Integration Points
### 1. Update SwarmCoordinator Constructor
```typescript
constructor(config: Partial<SwarmConfig> = {}) {
super();
// ... existing initialization ...
// Initialize optimizations
this.initializeOptimizations();
}
private initializeOptimizations() {
// Create optimized executor
this.optimizedExecutor = new OptimizedExecutor({
connectionPool: {
min: this.config.performance?.minConnections || 2,
max: this.config.performance?.maxConnections || 10
},
concurrency: this.config.performance?.maxConcurrentTasks || 10,
caching: {
enabled: this.config.performance?.enableCaching ?? true,
ttl: this.config.performance?.cacheTTL || 3600000
}
});
// Set up memory management
this.events = new CircularBuffer(1000);
this.tasks = new TTLMap({ defaultTTL: 3600000, maxSize: 10000 });
}
```
### 2. Update Task Execution
```typescript
async executeTask(taskId: string): Promise<void> {
const task = this.tasks.get(taskId);
if (!task || !task.assignedTo) return;
const agent = this.agents.get(task.assignedTo.id);
if (!agent) return;
try {
// Use optimized executor
const result = await this.optimizedExecutor.executeTask(task, agent.id);
// Update task with result
task.result = result;
task.status = 'completed';
// Emit completion event
this.emitSwarmEvent({
type: 'task.completed',
data: { task, result }
});
} catch (error) {
// Handle error...
}
}
```
## Performance Monitoring
Add metrics collection:
```typescript
// In SwarmCoordinator
getPerformanceMetrics() {
return {
executor: this.optimizedExecutor.getMetrics(),
connectionPool: this.optimizedExecutor.getConnectionPoolStats(),
fileManager: this.optimizedExecutor.getFileManagerMetrics(),
cache: this.optimizedExecutor.getCacheStats(),
memory: {
eventBufferSize: this.eventHistory.getSize(),
taskMapSize: this.tasks.size,
agentCount: this.agents.size
}
};
}
```
## Testing the Migration
1. **Unit Tests**: Update existing tests to work with async operations
2. **Integration Tests**: Test the full optimized flow
3. **Performance Tests**: Measure improvements
4. **Memory Tests**: Verify bounded memory usage
## Rollback Plan
If issues occur, you can disable optimizations with feature flags:
```typescript
const USE_OPTIMIZATIONS = process.env.SWARM_USE_OPTIMIZATIONS !== 'false';
if (USE_OPTIMIZATIONS) {
this.executor = new OptimizedExecutor(config);
} else {
this.executor = new LegacyExecutor(config);
}
```
## Next Steps
After Phase 1 implementation:
1. Monitor metrics for 24-48 hours
2. Verify 50% performance improvement
3. Check memory usage is bounded
4. Proceed to Phase 2 (Event-driven architecture)