Performance Features
Overview
Catzilla includes several performance optimizations designed to make your web applications fast and efficient. The framework leverages C acceleration for critical path operations while maintaining the ease of use of Python.
C-Accelerated Components
Route Matching
The core routing system is implemented in C, providing fast route matching:
Routes are stored in an optimized trie structure
Pattern matching is performed using efficient C algorithms
Path parameter extraction is handled in C code
Path Parameter Extraction
Parameter extraction from URLs happens in C:
@app.get("/users/{user_id}/posts/{post_id}")
def get_user_post(request):
# These parameters are extracted by C code
user_id = request.path_params["user_id"]
post_id = request.path_params["post_id"]
return {"user_id": user_id, "post_id": post_id}
Query Parameter Processing
Query parameters are also processed efficiently:
@app.get("/search")
def search(request):
# Query parameters loaded on demand
query = request.query_params.get("q", "")
page = request.query_params.get("page", "1")
return {"query": query, "page": page}
RouterGroup Efficiency
Organized Route Management
RouterGroups help organize routes efficiently:
# Routes are grouped logically for better organization
api = RouterGroup(prefix="/api/v1")
users = RouterGroup(prefix="/users")
posts = RouterGroup(prefix="/posts")
# Nested groups maintain performance
api.include_group(users)
api.include_group(posts)
app.include_routes(api)
Scalable Route Registration
RouterGroups scale well with large numbers of routes:
Route prefixes are resolved at registration time
No runtime overhead for group resolution
Efficient route storage and lookup
Performance Best Practices
Route Design
Design routes for optimal performance:
# Good: Simple patterns are fastest
@app.get("/users/{user_id}")
@app.get("/posts/{post_id}")
# Still efficient: Multiple parameters
@app.get("/users/{user_id}/posts/{post_id}")
# Complex but supported: Deeply nested parameters
@app.get("/api/v1/orgs/{org_id}/teams/{team_id}/projects/{project_id}")
RouterGroup Organization
Organize RouterGroups for clarity and maintainability:
# Organize by functionality
user_routes = RouterGroup(prefix="/users")
post_routes = RouterGroup(prefix="/posts")
admin_routes = RouterGroup(prefix="/admin")
# Or by API version
api_v1 = RouterGroup(prefix="/api/v1")
api_v2 = RouterGroup(prefix="/api/v2")
# Include groups efficiently
main_api = RouterGroup(prefix="/api")
main_api.include_group(api_v1)
main_api.include_group(api_v2)
app.include_routes(main_api)
Request Handler Efficiency
Write efficient request handlers:
@app.get("/users/{user_id}")
def get_user(request):
# Parameter extraction is already optimized
user_id = request.path_params["user_id"]
# Focus on your business logic efficiency
# Use database connection pooling
# Cache frequently accessed data
# Return appropriate response sizes
return {"user_id": user_id, "name": "John Doe"}
Memory Usage Tips
Keep memory usage efficient:
# Use appropriate data structures
@app.get("/large-data")
def get_large_data(request):
# Stream large responses when possible
# Don't load everything into memory at once
# Use generators for large datasets
return {"data": "appropriate_sized_response"}
Performance Monitoring
Request Timing
Monitor your application performance:
import time
@app.get("/monitored-endpoint")
def monitored_handler(request):
start_time = time.time()
# Your business logic here
result = {"message": "Hello World"}
# Log timing if needed
duration = time.time() - start_time
print(f"Request took {duration:.3f}s")
return result
Resource Usage
Keep an eye on resource usage:
# Monitor key metrics in production:
# - Request latency
# - Memory usage
# - Route matching performance
# - Parameter extraction overhead
# - Database query times
Scaling Considerations
Application Design
Design your application for scale:
Keep route handlers lightweight
Use efficient database queries
Implement appropriate caching
Consider async operations where beneficial
Monitor and profile your specific use cases
Route Organization
As your application grows:
Group related routes with RouterGroups
Keep route patterns as simple as possible
Avoid overly deep nesting when not necessary
Use descriptive parameter names
Scaling Considerations
Application Design
Design your application for scale:
Keep route handlers lightweight
Use efficient database queries
Implement appropriate caching
Consider async operations where beneficial
Monitor and profile your specific use cases
Route Organization
As your application grows:
Group related routes with RouterGroups
Keep route patterns as simple as possible
Avoid overly deep nesting when not necessary
Use descriptive parameter names
Testing Your Performance
Simple Benchmarking
You can benchmark your own Catzilla application:
import time
from catzilla import App
app = App()
@app.get("/test/{param}")
def test_route(request):
return {"param": request.path_params["param"]}
# Simple timing test
def benchmark_route():
# This would require setting up actual requests
# Use tools like wrk, ab, or locust for real load testing
pass
Load Testing Tools
For production load testing, use professional tools:
wrk: HTTP benchmarking tool
Apache Bench (ab): Simple load testing
Locust: Python-based load testing
Artillery: Modern load testing toolkit
Monitoring in Production
Monitor key metrics in your deployed applications:
import time
@app.middleware
def timing_middleware(request, call_next):
start_time = time.time()
response = call_next(request)
duration = time.time() - start_time
# Log or send to monitoring system
print(f"Request to {request.path} took {duration:.3f}s")
return response
The C-accelerated foundation in Catzilla provides a solid performance base for your applications. Focus on writing efficient business logic and following web development best practices for optimal performance.