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

  1. Latency (p50, p95, p99)

    • Target: p50 <100ms, p99 <500ms
  2. Throughput (req/s)

    • Target: >20 req/s per service
  3. Error Rate

    • Target: <0.1%
  4. 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

  1. Profile code: python -m cProfile
  2. Check for infinite loops in C tools
  3. Reduce concurrent operations

High Memory Usage

  1. Monitor with docker stats
  2. Check for memory leaks in C code
  3. Implement garbage collection tuning
  4. Use connection pooling

Slow Queries

  1. Run EXPLAIN QUERY PLAN
  2. Add missing indexes
  3. Verify statistics are current
  4. Consider query rewriting

Network Latency

  1. Check service co-location
  2. Verify DNS resolution
  3. Monitor with tcpdump
  4. Consider service mesh (istio)

Database Lock Issues

  1. Check for long-running transactions
  2. Verify concurrent access limits
  3. Consider read replicas
  4. 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