16. Performance Requirements
16.2 Resource Usage Limits
Memory Constraints
| Component |
Maximum |
Typical |
Notes |
| Backend (idle) |
100 MB |
~60 MB |
FastAPI + SQLite |
| Backend (processing) |
500 MB |
~200 MB |
With OCR active |
| Frontend (Electron) |
300 MB |
~180 MB |
React + Chromium |
| Database size (10K calculations) |
50 MB |
~25 MB |
SQLite file size |
| Single file upload |
10 MB |
1-5 MB |
Hard limit enforced |
CPU Usage
| Operation |
Maximum |
Typical |
| Idle state |
5% |
<1% |
| Single calculation |
10% |
~3% |
| Bulk processing (100 rows) |
40% |
~25% |
| OCR processing (active) |
80% |
~60% |
| UI rendering |
20% |
~8% |
Network (Local API Calls)
Fully Offline Application
All operations are local (localhost). No external network requests after dependencies are installed.
| API Endpoint |
Latency Target |
Actual |
| /api/v1/calculate |
< 10ms |
~3ms |
| /api/v1/history |
< 50ms |
~12ms |
| /api/v1/bulk/upload |
Variable |
~2-5s for 100 rows |
| /api/v1/settings |
< 20ms |
~6ms |
16.3 Optimization Strategies
Backend Optimizations
1. Database Indexing
-- Performance-critical indexes
CREATE INDEX idx_currency ON calculations(currency);
CREATE INDEX idx_timestamp ON calculations(timestamp DESC);
CREATE INDEX idx_currency_timestamp ON calculations(currency, timestamp DESC);
2. Decimal Precision (Financial Accuracy)
from decimal import Decimal, getcontext
# Set precision for financial calculations
getcontext().prec = 28 # 28 decimal places
# Always use Decimal for money
amount = Decimal("1850.50") # ? Correct
# amount = 1850.50 # ? Avoid floats for money
3. Batch Processing
# Bulk insert optimization
with db.begin():
for calc in calculations:
db.add(Calculation(**calc))
# Commits once at the end (faster than individual commits)
4. OCR Optimization
- Image preprocessing (grayscale, DPI normalization)
- Tesseract PSM mode optimization (mode 6 for text blocks)
- Confidence score filtering (>60%)
- Parallel processing for multi-page PDFs (future)
Frontend Optimizations
1. React Performance
// Use React.memo for expensive components
const BreakdownTable = React.memo(({ breakdown }) => {
// Component only re-renders if breakdown changes
});
// Debounce user input
const debouncedAmount = useDebounce(amount, 300);
2. Lazy Loading
// Code splitting for routes
const HistoryPage = lazy(() => import('./pages/HistoryPage'));
const BulkUploadPage = lazy(() => import('./pages/BulkUploadPage'));
3. Virtual Scrolling (Large Lists)
import { FixedSizeList } from 'react-window';
// Render only visible items for 1000+ row tables
{Row}
4. Caching
- React Query for API response caching
- LocalStorage for settings and language
- Memoization for expensive calculations
16.4 Scalability Considerations
Current Limits (Phase 1)
| Resource |
Current Limit |
Recommended Max |
| Database calculations |
No hard limit |
~100K records (optimal) |
| Bulk upload rows |
10,000 rows |
1,000-5,000 typical |
| History page size |
200 per page (max) |
50 default |
| Concurrent users |
1 (desktop app) |
N/A (single user) |
| File upload size |
10 MB |
1-5 MB optimal |
Future Scalability (Phase 2+)
- Cloud Sync: PostgreSQL backend for multi-device sync
- Multi-User: Authentication + user isolation
- API Rate Limiting: Prevent abuse in public API
- Horizontal Scaling: Load balancer + multiple backend instances
- CDN: Static asset delivery for web version
- Caching Layer: Redis for frequently accessed data
16.5 Performance Monitoring
Backend Logging
import logging
import time
logger = logging.getLogger(__name__)
# Performance logging decorator
def log_performance(func):
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
duration = time.perf_counter() - start
logger.info(f"{func.__name__} completed in {duration*1000:.2f}ms")
if duration > 1.0: # Warn if > 1s
logger.warning(f"Slow operation: {func.__name__} took {duration:.2f}s")
return result
return wrapper
@log_performance
def process_bulk_upload(file):
# Function implementation
pass
Frontend Performance Monitoring
// React component render tracking
useEffect(() => {
console.time('CalculatorPage render');
return () => {
console.timeEnd('CalculatorPage render');
};
}, []);
// API call timing
const fetchData = async () => {
const start = performance.now();
const response = await axios.get('/api/v1/history');
const duration = performance.now() - start;
console.log(`API call took ${duration.toFixed(2)}ms`);
return response.data;
};
Health Check Script
File: health-check.ps1
Write-Host "=== System Health Check ===" -ForegroundColor Cyan
# Check backend
$backendUrl = "http://localhost:8000/health"
try {
$response = Invoke-RestMethod -Uri $backendUrl -TimeoutSec 5
Write-Host "? Backend: HEALTHY" -ForegroundColor Green
Write-Host " Database: $($response.database)"
Write-Host " Version: $($response.version)"
} catch {
Write-Host "? Backend: OFFLINE" -ForegroundColor Red
}
# Check database size
$dbPath = "currency_calculator.db"
if (Test-Path $dbPath) {
$dbSize = (Get-Item $dbPath).Length / 1MB
Write-Host "? Database: $($dbSize.ToString('F2')) MB" -ForegroundColor Green
if ($dbSize > 50) {
Write-Host " WARNING: Database > 50MB (consider cleanup)" -ForegroundColor Yellow
}
}
# Check Tesseract
try {
$tesseractVersion = & tesseract --version 2>&1 | Select-Object -First 1
Write-Host "? Tesseract: $tesseractVersion" -ForegroundColor Green
} catch {
Write-Host "? Tesseract: NOT FOUND" -ForegroundColor Red
}
# Check Poppler
try {
$popplerVersion = & pdftoppm -v 2>&1 | Select-Object -First 1
Write-Host "? Poppler: $popplerVersion" -ForegroundColor Green
} catch {
Write-Host "? Poppler: NOT FOUND" -ForegroundColor Red
}
? Section Complete
This section documents comprehensive performance requirements: Core operations (<1ms single calc, <100ms for 100 calcs), File processing (<3s OCR, <500ms CSV), Database operations (<100ms queries), UI responsiveness (<2s page load), Resource limits (Backend: 100MB idle/500MB active, Frontend: 300MB, DB: 50MB for 10K records), Optimization strategies (indexing, Decimal precision, batching, React.memo), Scalability considerations, Performance monitoring scripts.