CPU Estimation Module¶
Module: 08_09_00_cpu_estimation
Phase: FASE 1 - CPU Estimation
Status: â
Complete
Overview¶
The CPU Estimation module provides static and runtime analysis tools for estimating CPU cost of audio processing components. It enables pre-deployment performance validation and real-time budget tracking.
Features¶
ðŊ Core Capabilities¶
- Static Cost Analysis - Estimate CPU cost without profiling
- Operation Counting - Track runtime operations atomically
- Budget Tracking - Monitor compliance with real-time constraints
- Component Analysis - Per-component cost breakdown
- Multi-level Validation - Safe, Warning, Critical, Exceeded states
ð Analysis Types¶
| Analysis Type | Description | Use Case |
|---|---|---|
| Static | Operation-based estimation | Pre-deployment validation |
| Runtime | Atomic operation counting | Development profiling |
| Budget | Real-time constraint checking | Production monitoring |
| Component | Per-component breakdown | Optimization targeting |
Architecture¶
08_09_00_cpu_estimation/
âââ include/
â âââ StaticCostAnalyzer.hpp # Static cost estimation
â âââ OperationCounter.hpp # Runtime operation counting
â âââ CPUBudgetTracker.hpp # Budget monitoring
âââ src/
â âââ StaticCostAnalyzer.cpp
â âââ OperationCounter.cpp
â âââ CPUBudgetTracker.cpp
âââ tests/
â âââ test_cpu_estimation.cpp # Catch2 tests
âââ examples/
â âââ cpu_estimation_demo.cpp # Complete workflow demo
â âââ cost_model_example.json # Example cost model
âââ CMakeLists.txt
Quick Start¶
1. Static Cost Analysis¶
#include <StaticCostAnalyzer.hpp>
using namespace audiolab::plugins::profiling;
StaticCostAnalyzer analyzer;
analyzer.setReferenceCPU(3.0f); // 3 GHz reference
// Analyze single component
auto profile = analyzer.analyzeComponent("filter1", "filter_biquad");
std::cout << "Estimated cycles: " << profile.estimatedCycles << "\n";
std::cout << "Estimated time: " << profile.estimatedMicroseconds << " Ξs\n";
// Analyze plugin with multiple components
std::vector<std::string> ids = {"filter1", "comp1", "reverb1"};
std::vector<std::string> types = {
"filter_biquad", "compressor_rms", "reverb_algorithmic"
};
auto profiles = analyzer.analyzePlugin(ids, types);
float totalCost = analyzer.getTotalCost(profiles);
2. Runtime Operation Counting¶
#include <OperationCounter.hpp>
OperationCounter counter;
// Manual counting
void processBlock(float* buffer, size_t numSamples) {
for (size_t i = 0; i < numSamples; ++i) {
counter.count("mul", 5);
counter.count("add", 4);
// ... processing ...
}
}
// RAII scoped counting
{
ScopedOpCounter scope(counter, "reverb_process");
processReverb();
} // Automatically increments count
// Generate report
std::cout << counter.generateReport();
3. Budget Tracking¶
#include <CPUBudgetTracker.hpp>
CPUBudgetTracker tracker;
tracker.setBudget(CPUBudgetTracker::getRealtimeNormalBudget());
// Set actual measured cost
tracker.setActualCost(actualMicroseconds);
// Check budget compliance
auto result = tracker.checkBudget();
if (result.status == BudgetStatus::Exceeded) {
std::cerr << "CPU budget exceeded!\n";
}
std::cout << "Utilization: " << tracker.getUtilization() << "%\n";
std::cout << tracker.generateReport();
4. Component Budget Breakdown¶
#include <CPUBudgetTracker.hpp>
ComponentBudgetTracker componentTracker;
// Track individual components
componentTracker.setComponentCost("filter", 50.0f);
componentTracker.setComponentCost("compressor", 150.0f);
componentTracker.setComponentCost("reverb", 500.0f);
// Get breakdown
auto breakdown = componentTracker.getCostBreakdown(); // Percentages
auto top3 = componentTracker.getTopComponents(3); // Most expensive
std::cout << componentTracker.generateReport();
Component Cost Models¶
Built-in Estimators¶
| Component Type | Operations/Sample | Estimated Cycles (3GHz) |
|---|---|---|
| Biquad Filter | 14 (5 mul, 4 add, 4 load, 1 store) | ~34 |
| RMS Compressor | 50 (20 mul, 15 add, 2 div, 1 sqrt, etc.) | ~141 |
| Simple Delay | 11 (3 mul, 2 add, 4 load, 2 store) | ~29 |
| Reverb | 150+ (complex algorithm) | ~300 |
Operation Costs (Default Model)¶
| Operation | Cycles | Variance | Category |
|---|---|---|---|
add |
1.0 | 0.2 | Arithmetic |
mul |
3.0 | 0.5 | Arithmetic |
div |
15.0 | 2.0 | Arithmetic |
sqrt |
12.0 | 1.5 | Arithmetic |
load |
3.0 | 1.0 | Memory |
store |
3.0 | 1.0 | Memory |
cache_miss |
100.0 | 50.0 | Memory |
branch |
1.0 | 2.0 | Control |
branch_miss |
20.0 | 10.0 | Control |
simd_add |
0.5 | 0.1 | SIMD |
simd_mul |
1.5 | 0.3 | SIMD |
Budget Presets¶
Real-time Budgets¶
// Strict: 256 samples @ 48kHz = 5.33 ms
auto strict = CPUBudgetTracker::getRealtimeStrictBudget();
// Warning: 70%, Critical: 85%
// Normal: 512 samples @ 48kHz = 10.67 ms
auto normal = CPUBudgetTracker::getRealtimeNormalBudget();
// Warning: 80%, Critical: 95%
// Relaxed: 1024 samples @ 48kHz = 21.33 ms
auto relaxed = CPUBudgetTracker::getRealtimeRelaxedBudget();
// Warning: 85%, Critical: 98%
// Offline: 4096 samples @ 48kHz = 85.33 ms
auto offline = CPUBudgetTracker::getOfflineBudget();
// No hard limits
Budget Status Levels¶
enum class BudgetStatus {
Safe, // Under warning threshold
Warning, // Between warning and critical
Critical, // Above critical threshold
Exceeded // Over 100% budget
};
Custom Cost Models¶
You can load custom cost models from JSON:
See cost_model_example.json for format.
Complete Workflow Example¶
// Step 1: Analyze plugin statically
StaticCostAnalyzer analyzer;
analyzer.setReferenceCPU(3.0f);
std::vector<std::string> ids = {"filter", "comp", "reverb"};
std::vector<std::string> types = {
"filter_biquad", "compressor_rms", "reverb_algorithmic"
};
auto profiles = analyzer.analyzePlugin(ids, types);
// Step 2: Track component costs
ComponentBudgetTracker componentTracker;
for (const auto& profile : profiles) {
componentTracker.setComponentCost(
profile.componentId,
profile.estimatedMicroseconds
);
}
// Step 3: Check budget compliance
CPUBudgetTracker budgetTracker;
budgetTracker.setBudget(CPUBudgetTracker::getRealtimeNormalBudget());
float totalCost = analyzer.getTotalCost(profiles);
budgetTracker.setActualCost(totalCost);
auto result = budgetTracker.checkBudget();
// Step 4: Generate reports
std::cout << budgetTracker.generateReport();
std::cout << componentTracker.generateReport();
// Step 5: Optimization recommendations
if (result.status >= BudgetStatus::Warning) {
auto top3 = componentTracker.getTopComponents(3);
std::cout << "Focus optimization on:\n";
for (const auto& [id, cost] : top3) {
std::cout << " - " << id << " (" << cost << " Ξs)\n";
}
}
Testing¶
Build and Run Tests¶
# Configure
cmake -B build -DBUILD_TESTING=ON
# Build
cmake --build build
# Run tests
cd build
ctest --output-on-failure
# Or run directly
./test_cpu_estimation
Test Coverage¶
- â Static cost analysis (all component types)
- â Operation counting (atomic, thread-safe)
- â Budget tracking (all status levels)
- â Component budget breakdown
- â Integration tests (complete workflow)
- â Report generation
Performance Characteristics¶
StaticCostAnalyzer¶
- Complexity: O(n) where n = number of components
- Memory: Minimal (cost model map)
- Thread-safety: Read-only after initialization
OperationCounter¶
- Complexity: O(1) per count operation
- Memory: O(m) where m = unique operation types
- Thread-safety: Lock-free atomics (relaxed ordering)
- Overhead: ~5-10 CPU cycles per count
CPUBudgetTracker¶
- Complexity: O(1) for all operations
- Memory: Minimal (budget config + counters)
- Thread-safety: Safe for concurrent reads
Real-Time Safety¶
RT-Safe Components¶
â OperationCounter::count() - Lock-free atomics â CPUBudgetTracker::setActualCost() - Simple assignment â All getters - Non-blocking reads
NOT RT-Safe¶
â Report generation - String allocation â Cost model loading - File I/O â Map insertions - Memory allocation
Integration with Other Modules¶
08_09_00_cpu_estimation
â (uses)
08_01_component_library (component metadata)
â (provides cost estimates to)
08_09_03_bottleneck_warnings
â (feeds optimization suggestions to)
08_09_04_optimization_suggestions
Future Enhancements¶
- Machine learning cost model calibration
- Platform-specific cost models (ARM, Apple Silicon)
- SIMD instruction cost analysis
- Cache simulation for memory cost
- Regression tracking over time
- Visual profiling reports (HTML/SVG)
Best Practices¶
1. Reference CPU Selection¶
Use a conservative reference CPU frequency (e.g., 2.5-3.0 GHz) to account for: - Laptop CPUs with lower base clocks - Thermal throttling - Background processes - OS overhead
2. Budget Thresholds¶
- Development: Use strict budgets (70% warning)
- Production: Use normal budgets (80% warning)
- Testing: Use relaxed budgets for stress testing
3. Component Granularity¶
Profile at component level, not individual operations:
// â
Good
counter.count("biquad_process");
// â Too granular for production
counter.count("mul");
counter.count("add");
4. Custom Cost Models¶
Calibrate cost models for your target platform:
# Run benchmark on target hardware
./bench_operations > my_platform_costs.json
# Load custom model
analyzer.loadCostModel("my_platform_costs.json");
5. Budget Validation¶
Always validate budgets during CI/CD:
Dependencies¶
- nlohmann/json - JSON parsing for cost models
- Catch2 - Testing framework
- C++20 -
<atomic>,<map>,<string>
License¶
Part of AudioLab Plugin Framework. See root LICENSE.
See Also¶
- 08_01_component_library - Component metadata
- 08_09_IMPLEMENTATION_PLAN.md - Full performance profiling roadmap
- 04_CORE/04_15_core_config - RT safety defaults
Module Status: â FASE 1 Complete Next: FASE 2 - Memory Prediction (08_09_01_memory_prediction)