7.5 KiB
7.5 KiB
MiroFish Optimization Implementation
Overview
Implementasi 5 optimasi untuk meningkatkan performance MiroFish simulation:
- Fix Memory Leak
- Checkpoint System
- Decision Caching
- Streaming Progress
- Batch Processing
Files Created
Backend Services
backend/app/services/checkpoint_manager.py- Save/restore simulation progressbackend/app/services/decision_cache.py- Cache LLM decisions to reduce API callsbackend/app/services/batch_processor.py- Memory-efficient batch processing
Backend API
backend/app/api/streaming.py- Real-time progress via Server-Sent Events
Optimized Scripts
backend/scripts/run_optimized_twitter_simulation.py- Optimized Twitter simulation runner
Usage
Run Optimized Simulation
cd backend
python scripts/run_optimized_twitter_simulation.py --config /path/to/simulation_config.json
# With options:
python scripts/run_optimized_twitter_simulation.py \
--config /path/to/config.json \
--max-rounds 50 \
--no-cache \ # Disable caching
--no-streaming \ # Disable streaming
--no-checkpoint # Disable checkpoint
Checkpoint Management
from app.services import CheckpointManager
# Check for existing checkpoint
if CheckpointManager.has_checkpoint("sim_xxx", "twitter"):
resume_round = CheckpointManager.get_resume_round("sim_xxx", "twitter")
print(f"Can resume from round {resume_round}")
# List checkpoints
checkpoints = CheckpointManager.list_checkpoints("sim_xxx")
for cp in checkpoints:
print(f"Round {cp['round_num']} at {cp['timestamp']}")
# Clear checkpoints
CheckpointManager.clear_checkpoints("sim_xxx")
Decision Caching
from app.services import DecisionCache
cache = DecisionCache.get_instance()
# Get cached decision
decision = cache.get(agent_id=1, context={
"personality": {...},
"visible_posts": [...],
"simulated_hour": 12,
})
if decision:
print(f"Using cached decision: {decision}")
else:
# Call LLM and cache result
decision = call_llm(...)
cache.set(agent_id=1, context=context, decision=decision)
# View stats
stats = cache.get_stats()
print(f"Cache hit rate: {stats['hit_rate']}")
Streaming Progress
from app.api.streaming import SimulationEventBroadcaster, create_stream_route
# In simulation runner
broadcaster = SimulationEventBroadcaster("sim_xxx")
broadcaster.simulation_start(total_rounds=96, total_agents=50)
broadcaster.round_complete(round_num=10, simulated_hour=5, ...)
broadcaster.simulation_complete(total_rounds=96, total_actions=1500, duration_seconds=3600)
# In Flask app/blueprint
from flask import Blueprint
simulation_bp = Blueprint('simulation', __name__)
create_stream_route(simulation_bp)
# Client-side (JavaScript)
const eventSource = new EventSource('/api/simulation/sim_xxx/stream');
eventSource.addEventListener('round_complete', (e) => {
const data = JSON.parse(e.data);
console.log(`Round ${data.round_num} complete - ${data.progress_percent}%`);
});
Batch Processing
from app.services import BatchProcessor, BatchProcessorConfig
config = BatchProcessorConfig(
batch_size=10,
batch_delay=0.5,
memory_cleanup_interval=5,
)
processor = BatchProcessor(config)
results = await processor.process_in_batches(
items=agents,
process_func=process_batch_func,
progress_callback=lambda current, total, progress: print(f"{progress:.1f}%"),
)
Expected Improvements
Memory Usage
- Before: 1-2 GB for 96 rounds
- After: 300-500 MB for 96 rounds
- Improvement: 60-75% reduction
API Calls
- Before: 2880-5760 calls for 96 rounds
- After: 2000-4000 calls (with 30% cache hit rate)
- Improvement: 20-40% reduction
Reliability
- Can resume from checkpoint if crash
- Graceful error handling per batch
- Real-time progress visibility
Performance
- Memory cleanup prevents OOM
- Batch processing stabilizes memory
- Streaming prevents "stuck" perception
Configuration
Environment Variables
# .env file
# LLM Configuration
LLM_API_KEY=your_api_key
LLM_BASE_URL=https://api.openai.com/v1
LLM_MODEL_NAME=gpt-4o-mini
# Zep Cloud
ZEP_API_KEY=your_zep_key
# Simulation Optimization (optional)
CHECKPOINT_INTERVAL=10 # Save checkpoint every N rounds
BATCH_SIZE=10 # Process N agents per batch
MAX_CACHE_TTL=24 # Cache TTL in hours
MEMORY_CLEANUP_INTERVAL=5 # GC every N rounds
Python Config
# In OptimizedTwitterSimulationRunner
CHECKPOINT_INTERVAL = 10 # Save every 10 rounds
BATCH_SIZE = 10 # 10 agents per batch
MAX_CACHE_TTL = 24 # 24 hour cache TTL
MEMORY_CLEANUP_INTERVAL = 5 # GC every 5 rounds
Monitoring
Cache Statistics
cache = DecisionCache.get_instance()
stats = cache.get_stats()
# {
# "hits": 150,
# "misses": 100,
# "hit_rate": "60.0%",
# "cache_size": 250
# }
Batch Statistics
stats = processor.get_stats(results)
# {
# "total_batches": 96,
# "total_success": 1400,
# "total_errors": 5,
# "total_duration": 3600.5,
# "avg_batch_duration": 37.5,
# "success_rate": "99.6%"
# }
Checkpoint Status
checkpoints = CheckpointManager.list_checkpoints("sim_xxx")
# [
# {"file": "checkpoint_twitter_0096.json.gz", "round_num": 96, "timestamp": "2026-07-09T01:00:00"},
# {"file": "checkpoint_twitter_0090.json.gz", "round_num": 90, "timestamp": "2026-07-09T00:50:00"},
# ]
Integration with Existing Code
Use Optimized Runner
# Instead of:
# from scripts.run_twitter_simulation import TwitterSimulationRunner
# Use:
from scripts.run_optimized_twitter_simulation import OptimizedTwitterSimulationRunner
runner = OptimizedTwitterSimulationRunner(
config_path=config_path,
enable_caching=True,
enable_streaming=True,
enable_checkpoint=True,
)
await runner.run(max_rounds=96)
Add Streaming to Existing Routes
# In backend/app/api/simulation.py
from .streaming import create_stream_route
# Add streaming route
create_stream_route(simulation_bp)
Add Checkpoint to Existing Runner
# In your simulation loop
from app.services import CheckpointManager
for round_num in range(total_rounds):
# ... simulation logic ...
# Save checkpoint every 10 rounds
if (round_num + 1) % 10 == 0:
CheckpointManager.save_checkpoint(
simulation_id=simulation_id,
round_num=round_num + 1,
state={"current_round": round_num + 1},
platform="twitter",
)
Troubleshooting
Memory Still High?
- Reduce
BATCH_SIZEto 5 - Increase
MEMORY_CLEANUP_INTERVALto 3 - Disable caching if not needed
- Check for memory leaks in custom code
Simulation Slow?
- Check LLM API latency
- Reduce
batch_delayto 0.1 - Increase
BATCH_SIZEto 20 (if memory allows) - Check cache hit rate - should be 20-40%
Checkpoint Not Saving?
- Check directory permissions
- Check disk space
- Verify
simulation_idis correct - Check logs for errors
Streaming Not Working?
- Check Flask route is registered
- Check client connects to correct URL
- Check browser supports EventSource
- Check for proxy buffering (disable with X-Accel-Buffering: no)
Future Improvements
- Redis Cache - For distributed caching across multiple workers
- PostgreSQL - Instead of SQLite for better concurrency
- Kubernetes Jobs - For scalable simulation execution
- WebSocket - For bidirectional streaming (not just SSE)
- Metrics Dashboard - Real-time Grafana dashboard for monitoring