Memory Prediction Module¶
Module: 08_09_01_memory_prediction
Phase: FASE 2 - Memory Prediction
Status: ✅ Complete
Overview¶
The Memory Prediction module provides comprehensive memory analysis tools for audio processing components, covering stack usage, heap allocations, and memory layout optimization. Essential for embedded systems, real-time safety validation, and performance optimization.
Features¶
🎯 Core Capabilities¶
- Stack Usage Calculation - Static analysis of stack memory requirements
- Heap Allocation Detection - Runtime and static detection of allocations
- Memory Layout Optimization - Struct/class layout analysis and optimization
- Cache Line Analysis - Cache utilization and false sharing detection
- Real-Time Safety - Validation of RT constraints
📊 Analysis Types¶
| Analysis Type | Tool | Use Case |
|---|---|---|
| Stack | StackUsageCalculator | Embedded systems, RT budgets |
| Heap | HeapAllocationDetector | RT safety validation |
| Layout | MemoryLayoutOptimizer | Performance optimization |
| Cache | MemoryLayoutOptimizer | False sharing prevention |
Architecture¶
08_09_01_memory_prediction/
├── include/
│ ├── StackUsageCalculator.hpp # Stack usage analysis
│ ├── HeapAllocationDetector.hpp # Heap allocation tracking
│ └── MemoryLayoutOptimizer.hpp # Layout optimization
├── src/
│ ├── StackUsageCalculator.cpp
│ ├── HeapAllocationDetector.cpp
│ └── MemoryLayoutOptimizer.cpp
├── tests/
│ └── test_memory_prediction.cpp # Catch2 tests
├── examples/
│ └── memory_prediction_demo.cpp # Complete demos
└── CMakeLists.txt
Quick Start¶
1. Stack Usage Analysis¶
#include <StackUsageCalculator.hpp>
using namespace audiolab::plugins::profiling;
StackUsageCalculator calculator;
// Analyze component
auto profile = calculator.analyzeComponent("reverb", "reverb_algorithmic");
std::cout << "Stack usage: " << profile.total << " bytes\n";
std::cout << "Max depth: " << profile.maxDepth << "\n";
// Check budget
auto check = calculator.checkBudget(StackBudgets::EMBEDDED_MEDIUM);
if (!check.withinBudget) {
std::cerr << "Exceeds stack budget!\n";
}
2. Heap Allocation Detection¶
#include <HeapAllocationDetector.hpp>
HeapAllocationDetector detector;
// Mark real-time context
void audioCallback() {
ScopedRealtimeContext rtGuard(detector);
// Any allocations here will be flagged as violations
processAudio();
}
// Check violations
if (detector.getRealtimeViolationCount() > 0) {
std::cerr << detector.generateViolationReport();
}
3. Memory Layout Optimization¶
#include <MemoryLayoutOptimizer.hpp>
MemoryLayoutOptimizer optimizer;
// Define struct fields
std::vector<MemoryLayoutOptimizer::FieldDef> fields = {
{"bool", "bypass", 1},
{"float", "gain", 4},
{"double", "sampleRate", 8},
{"int", "bufferSize", 4}
};
// Optimize layout
auto optimized = optimizer.optimizeLayout("ProcessorState", fields);
std::cout << "Bytes saved: " << optimized.bytesSaved << "\n";
std::cout << "Improvement: " << optimized.improvementPercent << "%\n";
std::cout << "\nOptimized code:\n" << optimized.generatedCode;
Stack Usage Calculator¶
Features¶
- Static Cost Analysis - Estimate stack usage without runtime profiling
- Component Models - Built-in models for common audio components
- Call Depth Tracking - Maximum function call depth analysis
- Recursive Detection - Identify recursive functions
- Budget Validation - Check against embedded/desktop budgets
Stack Budgets¶
namespace StackBudgets {
constexpr size_t EMBEDDED_TINY = 1024; // 1 KB - Microcontrollers
constexpr size_t EMBEDDED_SMALL = 4096; // 4 KB - ARM Cortex-M
constexpr size_t EMBEDDED_MEDIUM = 16384; // 16 KB - Embedded Linux
constexpr size_t DESKTOP_SAFE = 65536; // 64 KB - Desktop safe
constexpr size_t DESKTOP_NORMAL = 262144; // 256 KB - Typical desktop
}
Usage Example¶
StackUsageCalculator calc;
// Analyze plugin components
std::vector<std::string> ids = {"filter", "comp", "reverb"};
std::vector<std::string> types = {
"filter_biquad", "compressor_rms", "reverb_algorithmic"
};
auto profiles = calc.analyzePlugin(ids, types);
// Get top stack users
auto top3 = calc.getTopStackUsers(3);
for (const auto& [id, usage] : top3) {
std::cout << id << ": " << usage << " bytes\n";
}
// Check budget
auto check = calc.checkBudget(StackBudgets::EMBEDDED_MEDIUM);
std::cout << "Utilization: " << (check.utilization * 100) << "%\n";
Heap Allocation Detector¶
Features¶
- Static Analysis - Scan source files for allocation patterns
- Runtime Tracking - Track allocations in dev/test builds
- Real-Time Context - Mark RT threads for violation detection
- Pattern Detection - Find
new,malloc, STL containers, smart pointers - Component Breakdown - Per-component allocation summary
Allocation Types Detected¶
enum class Type {
New, // operator new
NewArray, // operator new[]
Malloc, // malloc/calloc/realloc
STLContainer, // std::vector, std::map, etc.
SmartPointer, // std::make_shared/unique
Unknown
};
Real-Time Safety Example¶
HeapAllocationDetector detector;
// Init phase (allocations allowed)
detector.trackAllocation("prepare", 8192, AllocationInfo::Type::NewArray);
// Audio callback (NO allocations allowed)
void processBlock() {
ScopedRealtimeContext rt(detector);
// Clean RT code here
// Any allocation triggers violation
}
// Check violations
if (detector.getRealtimeViolationCount() > 0) {
std::cerr << "❌ RT Safety Violated!\n";
std::cerr << detector.generateViolationReport();
}
Component Summary¶
auto summary = detector.getComponentSummary("reverb");
std::cout << "Component: " << summary.componentId << "\n";
std::cout << "Total allocations: " << summary.totalAllocations << "\n";
std::cout << "Total bytes: " << summary.totalBytes << "\n";
std::cout << "RT violations: " << summary.realtimeViolations << "\n";
Memory Layout Optimizer¶
Features¶
- Padding Analysis - Identify wasted padding bytes
- Field Reordering - Suggest optimal field ordering
- Cache Line Optimization - Align hot data to cache boundaries
- False Sharing Detection - Prevent cross-core cache conflicts
- Code Generation - Generate optimized struct definitions
Layout Analysis¶
MemoryLayoutOptimizer optimizer;
std::vector<MemoryLayoutOptimizer::FieldDef> fields = {
{"bool", "bypass", 1},
{"float", "gain", 4},
{"int", "mode", 4},
{"double", "phase", 8}
};
auto analysis = optimizer.analyzeLayout("State", fields);
std::cout << "Total size: " << analysis.totalSize << "\n";
std::cout << "Padding waste: " << analysis.paddingSize << "\n";
std::cout << "Efficiency: " << (analysis.efficiency * 100) << "%\n";
Optimization Workflow¶
// 1. Analyze original layout
auto original = optimizer.analyzeLayout("ProcessorState", fields);
// 2. Get optimized layout
auto optimized = optimizer.optimizeLayout("ProcessorState", fields);
std::cout << "Bytes saved: " << optimized.bytesSaved << "\n";
std::cout << "Improvement: " << optimized.improvementPercent << "%\n";
// 3. Use generated code
std::cout << optimized.generatedCode;
// Output:
// struct ProcessorState_Optimized {
// double phase; // 8-byte aligned first
// float gain;
// int mode;
// bool bypass;
// };
Cache Line Analysis¶
auto cache = optimizer.analyzeCacheUtilization("HotStruct", fields);
std::cout << "Cache lines used: " << cache.cacheLinesUsed << "\n";
if (cache.falseSharingRisk) {
std::cout << "⚠️ False sharing risk!\n";
for (const auto& field : cache.falseSharingFields) {
std::cout << " - " << field << "\n";
}
}
if (cache.splitAcrossCacheLines) {
std::cout << "⚠️ Fields split across cache lines:\n";
for (const auto& field : cache.splitFields) {
std::cout << " - " << field << "\n";
}
}
False Sharing Prevention¶
// Bad: Multiple atomics in same cache line
struct BadCounter {
std::atomic<int> counter1; // Cache line 0
std::atomic<int> counter2; // Cache line 0 - FALSE SHARING!
};
// Good: Separate cache lines
struct alignas(64) GoodCounter {
std::atomic<int> counter1;
char padding[64 - sizeof(std::atomic<int>)];
};
Testing¶
Build and Run Tests¶
# Configure
cmake -B build -DBUILD_TESTING=ON
# Build
cmake --build build --config Release
# Run tests
cd build
ctest --output-on-failure
# Or run directly
./Release/test_memory_prediction.exe
Test Coverage¶
- ✅ Stack usage analysis (all component types)
- ✅ Manual stack tracking
- ✅ Budget validation
- ✅ Heap allocation detection (all types)
- ✅ Real-time context tracking
- ✅ Violation reporting
- ✅ Layout analysis and optimization
- ✅ Cache line analysis
- ✅ False sharing detection
- ✅ Code generation
- ✅ Integration workflows
Examples¶
Run Demo¶
Demo Coverage¶
- Stack Usage - Component analysis, budget validation, top users
- Heap Allocation - Init vs RT phase, violation detection
- Memory Layout - Analysis, optimization, cache utilization
- Complete Workflow - Full memory analysis pipeline
Performance Characteristics¶
StackUsageCalculator¶
- Complexity: O(n) where n = components
- Memory: O(n) profile storage
- Thread-safety: Read-only after analysis
HeapAllocationDetector¶
- Complexity: O(1) per tracked allocation
- Memory: O(m) where m = allocations (bounded by config)
- Thread-safety: Safe for concurrent tracking
MemoryLayoutOptimizer¶
- Complexity: O(n log n) for field reordering
- Memory: Minimal (transient analysis)
- Thread-safety: Stateless analysis (thread-safe)
Real-Time Safety¶
RT-Safe Operations¶
✅ StackUsageCalculator::getTotalStackUsage() - Simple arithmetic ✅ StackUsageCalculator::getComponentProfile() - Map lookup ✅ HeapAllocationDetector::trackAllocation() - Vector push (pre-reserved)
NOT RT-Safe¶
❌ Report generation - String allocation ❌ Static analysis - File I/O ❌ Layout optimization - Vector sorting
Integration with Other Modules¶
08_09_01_memory_prediction
↓ (provides data to)
08_09_03_bottleneck_warnings (memory bottlenecks)
↓ (feeds)
08_09_04_optimization_suggestions (memory optimizations)
Best Practices¶
1. Stack Budget Selection¶
// Embedded systems - use conservative budgets
auto check = calc.checkBudget(StackBudgets::EMBEDDED_MEDIUM);
// Desktop - more relaxed
auto check = calc.checkBudget(StackBudgets::DESKTOP_SAFE);
2. Real-Time Validation¶
// Always validate RT threads in dev/test builds
#ifdef DEBUG
ScopedRealtimeContext rtGuard(detector);
#endif
processAudio(); // Will catch allocations in debug builds
3. Layout Optimization Priority¶
// Focus on hot paths first
if (analysis.efficiency < 0.75f) {
// Optimize this struct
auto opt = optimizer.optimizeLayout(name, fields);
}
4. False Sharing Prevention¶
// Separate frequently modified fields
struct alignas(64) RTSafeState {
std::atomic<float> parameterValue; // Own cache line
char padding[64 - sizeof(std::atomic<float>)];
// Cold data can share cache lines
bool initialized;
int version;
};
Common Patterns¶
Complete Memory Analysis¶
void analyzeComponent(const std::string& id, const std::string& type) {
// 1. Stack analysis
StackUsageCalculator stackCalc;
auto stackProfile = stackCalc.analyzeComponent(id, type);
// 2. Heap tracking
HeapAllocationDetector heapDetector;
heapDetector.beginRealtimeContext();
// ... process ...
heapDetector.endRealtimeContext();
// 3. Layout optimization
MemoryLayoutOptimizer layoutOpt;
// ... analyze layouts ...
// 4. Report
std::cout << "Stack: " << stackProfile.total << " bytes\n";
std::cout << "RT violations: " << heapDetector.getRealtimeViolationCount() << "\n";
}
Dependencies¶
- C++20 -
<atomic>,<optional>,<chrono> - Catch2 - Testing framework
Future Enhancements¶
- DWARF debug info parsing for precise stack analysis
- Address sanitizer integration
- Valgrind massif integration
- Memory pool analysis
- Fragmentation tracking
- Platform-specific optimizations (ARM, x86, Apple Silicon)
See Also¶
- 08_09_00_cpu_estimation - CPU cost estimation
- 08_09_IMPLEMENTATION_PLAN.md - Full profiling roadmap
- 04_CORE/04_04_realtime_safety - RT primitives
Module Status: ✅ FASE 2 Complete Next: FASE 3 - Hotspot Identification (08_09_02_hotspot_identification)