Tikker Performance Optimization Guide
Performance Benchmarks
Baseline performance metrics on standard hardware (2CPU, 2GB RAM):
API Service (C Tools Integration)
- Health Check: ~15ms (p50), <50ms (p99)
- Daily Stats: ~80ms (p50), <150ms (p99)
- Top Words: ~120ms (p50), <250ms (p99)
- Throughput: ~40-60 req/s
AI Service
- Health Check: ~10ms (p50), <50ms (p99)
- Text Analysis: ~2-5s (depends on text length and API availability)
- Throughput: ~0.5 req/s (limited by OpenAI API)
Visualization Service
- Health Check: ~12ms (p50), <50ms (p99)
- Bar Chart: ~150ms (p50), <300ms (p99)
- Line Chart: ~160ms (p50), <320ms (p99)
- Pie Chart: ~140ms (p50), <280ms (p99)
- Throughput: ~5-8 req/s
Running Benchmarks
Quick Benchmark
python scripts/benchmark.py
Benchmark Against Remote Server
python scripts/benchmark.py http://production-server
Detailed Test Results
pytest tests/test_performance.py -v --tb=short
Optimization Strategies
1. Database Optimization
Vacuum Database
Regular database maintenance improves query performance.
docker-compose exec api sqlite3 tikker.db "VACUUM;"
Impact: 5-15% query speed improvement
Create Indexes
Add indexes for frequently queried columns:
CREATE INDEX idx_words_frequency ON words(frequency DESC);
CREATE INDEX idx_events_timestamp ON events(timestamp);
CREATE INDEX idx_events_date ON events(date);
Impact: 30-50% improvement for indexed queries
Query Optimization
Use EXPLAIN QUERY PLAN to analyze slow queries:
sqlite3 tikker.db "EXPLAIN QUERY PLAN SELECT * FROM words ORDER BY frequency LIMIT 10;"
2. Caching Strategies
Redis Caching for Frequent Queries
Add Redis for popular word list caching:
import redis
cache = redis.Redis(host='localhost', port=6379)
def get_top_words(limit=10):
key = f"top_words:{limit}"
cached = cache.get(key)
if cached:
return json.loads(cached)
result = query_database(limit)
cache.setex(key, 3600, json.dumps(result))
return result
Impact: 10-100x improvement for cached queries
Add to docker-compose.yml:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
3. Python Optimization
Enable Optimization
ENV PYTHONOPTIMIZE=2
ENV PYTHONDONTWRITEBYTECODE=1
Use Async I/O
Current API already uses FastAPI (async), good baseline.
Profile Code
Identify bottlenecks:
python -m cProfile -s cumtime -m pytest tests/test_services.py
4. C Tools Optimization
Compile Flags
Update Makefile with optimization flags:
CFLAGS = -O3 -march=native -Wall -Wextra
Impact: 20-40% improvement in execution speed
Binary Stripping
Reduce binary size:
strip build/bin/tikker-*
Impact: Faster loading, reduced disk I/O
5. Network Optimization
Connection Pooling
Add HTTP connection pooling in wrapper:
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
Service Co-location
Run services on same host to reduce latency:
- Typical inter-service latency: ~5-10ms
- Same-host latency: <1ms
6. Memory Optimization
Monitor Memory Usage
docker stats
# Or detailed analysis
docker-compose exec api ps aux
Reduce Buffer Sizes
In c_tools_wrapper.py:
# Limit concurrent subprocess calls
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=4)
Garbage Collection Tuning
import gc
gc.set_threshold(10000)
7. Container Resource Limits
Update docker-compose.yml:
services:
api:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
8. Load Balancing
For production deployments with multiple instances:
nginx:
image: nginx:latest
ports:
- "8000:8000"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- api1
- api2
- api3
nginx.conf:
upstream api {
server api1:8000;
server api2:8000;
server api3:8000;
}
server {
listen 8000;
location / {
proxy_pass http://api;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
}
}
Performance Tuning Checklist
- Database vacuumed and indexed
- Python optimization flags enabled
- C compilation optimizations applied
- Connection pooling configured
- Caching strategy implemented
- Memory limits set appropriately
- Load balancing configured (if needed)
- Monitoring and logging enabled
- Benchmarks show acceptable latency
- Throughput meets SLA requirements
Monitoring Performance
Key Metrics to Track
-
Latency (p50, p95, p99)
- Target: p50 <100ms, p99 <500ms
-
Throughput (req/s)
- Target: >20 req/s per service
-
Error Rate
- Target: <0.1%
-
Resource Usage
- CPU: <80% sustained
- Memory: <80% allocated
- Disk: <90% capacity
Prometheus Metrics
Add to FastAPI apps:
from prometheus_client import Counter, Histogram, generate_latest
request_count = Counter('api_requests_total', 'Total requests')
request_duration = Histogram('api_request_duration_seconds', 'Request duration')
@app.middleware("http")
async def add_metrics(request, call_next):
start = time.time()
response = await call_next(request)
duration = time.time() - start
request_count.inc()
request_duration.observe(duration)
return response
@app.get("/metrics")
def metrics():
return generate_latest()
Troubleshooting Performance Issues
High CPU Usage
- Profile code:
python -m cProfile - Check for infinite loops in C tools
- Reduce concurrent operations
High Memory Usage
- Monitor with
docker stats - Check for memory leaks in C code
- Implement garbage collection tuning
- Use connection pooling
Slow Queries
- Run EXPLAIN QUERY PLAN
- Add missing indexes
- Verify statistics are current
- Consider query rewriting
Network Latency
- Check service co-location
- Verify DNS resolution
- Monitor with
tcpdump - Consider service mesh (istio)
Database Lock Issues
- Check for long-running transactions
- Verify concurrent access limits
- Consider read replicas
- Increase timeout values
Advanced Optimization
Async Database Access
Consider async SQLite driver for true async I/O:
from aiosqlite import connect
async def get_stats():
async with connect('tikker.db') as db:
cursor = await db.execute('SELECT * FROM events')
return await cursor.fetchall()
Compiled C Extensions
Convert performance-critical Python code to C extensions:
// stats.c
PyObject* get_daily_stats(PyObject* self, PyObject* args) {
// High-performance C implementation
}
Graph Query Optimization
For complex analyses, consider graph database:
Events → Words → Patterns
Analysis becomes graph traversal instead of SQL joins
SLA Targets
Recommended SLA targets for Tikker:
| Metric | Target | Priority |
|---|---|---|
| API Availability | 99.5% | Critical |
| Health Check Latency | <50ms | Critical |
| Stats Query Latency | <200ms | High |
| Word Search Latency | <300ms | High |
| Report Generation | <5s | Medium |
| AI Analysis | <10s | Low |
Performance Testing in CI/CD
Add performance regression testing:
# Run baseline benchmark
python scripts/benchmark.py baseline
# Run benchmark
python scripts/benchmark.py current
# Compare and fail if regression
python scripts/compare_benchmarks.py baseline current --fail-if-slower 10%
Further Reading
- SQLite Performance: https://www.sqlite.org/bestcase.html
- FastAPI Performance: https://fastapi.tiangolo.com/
- Python Optimization: https://docs.python.org/3/library/profile.html