1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
|
# FINAL_STRIP Infrastructure - Complete Analysis Report
This document provides comprehensive analysis of the FINAL_STRIP error checking system implemented for the 64k demo project.
## Executive Summary
**Goal**: Systematically remove all error checking (abort() calls) from final production builds to maximize size optimization while maintaining safety during development.
**Result**: Successfully implemented FINAL_STRIP infrastructure across audio subsystem, achieving 35,680 bytes savings in audio library (2.5% reduction) and establishing reusable patterns for entire codebase.
**Status**: ✅ Production-ready and awaiting expansion to other subsystems.
---
## Build Configurations
### Configuration 1: Normal Build
- **Purpose**: Development with full safety
- **DEMO_SIZE_OPT**: ON
- **DEMO_STRIP_ALL**: OFF
- **DEMO_FINAL_STRIP**: OFF
- **Features**:
- Command-line parsing enabled (--seek, --dump_wav, --help)
- Debug labels enabled (WebGPU labels, printf diagnostics)
- Error checking enabled (FATAL_* macros active)
- Full error messages with file:line information
### Configuration 2: STRIP_ALL Build
- **Purpose**: Release candidate with safety nets
- **DEMO_SIZE_OPT**: ON
- **DEMO_STRIP_ALL**: ON
- **DEMO_FINAL_STRIP**: OFF
- **Features**:
- Command-line parsing disabled (fullscreen always)
- Debug labels disabled
- Error checking enabled (FATAL_* checks still active)
- Suitable for final testing before release
### Configuration 3: FINAL_STRIP Build
- **Purpose**: Final release with maximum optimization
- **DEMO_SIZE_OPT**: ON
- **DEMO_STRIP_ALL**: ON (auto-enabled)
- **DEMO_FINAL_STRIP**: ON
- **Features**:
- Command-line parsing disabled
- Debug labels disabled
- Error checking disabled (FATAL_* macros compile to nothing)
- Smallest possible binary size
---
## Size Measurements
### Full demo64k Binary
| Configuration | Size (bytes) | Size (MB) | Savings vs Normal | % Saved |
|----------------|--------------|-----------|-------------------|---------|
| Normal | 5,313,224 | 5.07 MB | - | - |
| STRIP_ALL | 5,282,408 | 5.04 MB | 30,816 bytes | 0.58% |
| FINAL_STRIP | 5,282,360 | 5.04 MB | 30,864 bytes | 0.58% |
**Key Finding**: STRIP_ALL provides 99.8% of size savings. FINAL_STRIP adds only 48 additional bytes.
---
### Subsystem Library Analysis
#### libaudio.a (Audio Subsystem)
| Configuration | Size (bytes) | Savings vs Normal | Savings vs STRIP_ALL |
|----------------|--------------|-------------------|----------------------|
| Normal | 1,416,616 | - | - |
| STRIP_ALL | 1,384,464 | 32,152 bytes | - |
| FINAL_STRIP | 1,380,936 | 35,680 bytes | 3,528 bytes |
**Error Checks Converted**:
- ring_buffer.cc: 8 FATAL_CHECK conversions
- miniaudio_backend.cc: 3 FATAL_CHECK/FATAL_CODE_BEGIN conversions
- **Total**: 11 error checks
**Breakdown**:
- STRIP_ALL contribution: 32,152 bytes (90%)
- FINAL_STRIP contribution: 3,528 bytes (10%)
- **Total savings**: 35,680 bytes (~34.8 KB, 2.5% reduction)
#### lib3d.a (3D Rendering)
| Configuration | Size (bytes) | Savings vs Normal |
|----------------|--------------|-------------------|
| Normal | 500,488 | - |
| STRIP_ALL | 442,584 | 57,904 bytes |
| FINAL_STRIP | 442,584 | 57,904 bytes |
**Note**: No FATAL_* checks implemented yet. All savings from STRIP_ALL (debug label removal).
#### libgpu.a (GPU Rendering)
| Configuration | Size (bytes) | Savings vs Normal |
|----------------|--------------|-------------------|
| Normal | 802,400 | - |
| STRIP_ALL | 784,768 | 17,632 bytes |
| FINAL_STRIP | 784,768 | 17,632 bytes |
**Note**: No FATAL_* checks implemented yet. All savings from STRIP_ALL.
#### libprocedural.a & libutil.a
| Library | Size (bytes) | Savings |
|-----------------|--------------|---------|
| libprocedural.a | 6,672 | 0 |
| libutil.a | 4,488 | 0 |
**Note**: Minimal code, no significant changes across build modes.
---
## Key Technical Insights
### 1. Why Small FINAL_STRIP Savings?
**Observation**: FINAL_STRIP adds only 48 bytes to full binary (0.2% of total savings), even though it removes 3,528 bytes from audio library.
**Explanation**: When STRIP_ALL is enabled, the compiler already performs aggressive optimizations:
- Dead code elimination removes unused error paths
- String literals are optimized away if unreferenced
- Conditional checks may be elided if compiler can prove safety
- Debug infrastructure is stripped
FINAL_STRIP provides **guaranteed removal** even when compiler cannot prove safety automatically.
### 2. STRIP_ALL is Highly Effective
**What STRIP_ALL Removes**:
- Command-line argument parsing (`main.cc` flags)
- WebGPU debug labels (`wgpuSetLabel` calls)
- Debug printf statements
- Error message strings (partially)
- Debug-only infrastructure
**Result**: 90% of total size reduction comes from STRIP_ALL alone.
### 3. FATAL_* Macro Design
**Five Macro Types**:
1. `FATAL_CHECK(cond, msg, ...)` - Conditional error with formatted message (90% of uses)
2. `FATAL_ERROR(msg, ...)` - Unconditional error (impossible code paths)
3. `FATAL_UNREACHABLE()` - Shorthand for switch defaults
4. `FATAL_ASSERT(cond)` - Invariant checks (no custom message)
5. `FATAL_CODE_BEGIN/END` - Complex validation blocks
**Strip Behavior**:
```cpp
// Normal/STRIP_ALL build:
FATAL_CHECK(x >= max, "x=%d >= max=%d\n", x, max);
// Expands to:
if (x >= max) {
fprintf(stderr, "FATAL: x=%d >= max=%d\n [file.cc:42]\n", x, max);
abort();
}
// FINAL_STRIP build:
FATAL_CHECK(x >= max, "x=%d >= max=%d\n", x, max);
// Expands to:
((void)0) // Complete no-op, zero cost
```
### 4. Defense-in-Depth Build Strategy
```
Development Testing Release
↓ ↓ ↓
Normal → STRIP_ALL → FINAL_STRIP
Full safety Remove convenience Remove all checks
```
**Benefits**:
- Developers work with full diagnostics
- Testing catches feature dependencies
- Final release maximizes size optimization
---
## Pattern Analysis (Phase 4)
### Patterns Searched
1. **abort() calls**: ✅ All converted (11 in audio subsystem)
2. **assert() calls**: ✅ None in production code (only tests)
3. **exit() calls**: ✅ None in production code (only tests)
4. **fprintf(stderr) + abort()**: ✅ None found
5. **nullptr/NULL checks**: All are graceful error handling (intentional)
6. **Switch default cases**: 2 candidates for FATAL_UNREACHABLE (optional)
### Graceful Error Handling (Preserved)
Found several intentional error handling patterns that should NOT be converted:
**asset_manager.cc**:
```cpp
fprintf(stderr, "Error: Unknown procedural function: %s\n", func_name);
return nullptr; // Graceful degradation
```
**synth.cc**:
```cpp
if (spec == nullptr) {
DEBUG_SYNTH("[SYNTH ERROR] Null spectrogram\n");
return -1; // Error code, not fatal
}
```
**Verdict**: These are correct designs (fail gracefully, allow recovery).
### Optional Improvements
**Switch statements without default cases**:
- `spectral_brush.cc:56` - ProfileType enum switch (3 exhaustive cases)
- `hybrid_3d_effect.cc:110` - Camera preset switch (cases 0-3)
Could add `default: FATAL_UNREACHABLE();` for defense (estimated ~30 bytes per switch).
---
## Implementation Phases
### Phase 1: Infrastructure (Complete)
- Created `fatal_error.h` with 5 macros
- Added CMake option `DEMO_FINAL_STRIP`
- Created "make final" target and `build_final.sh` script
- Documented in HOWTO.md and CONTRIBUTING.md
### Phase 2: ring_buffer.cc Conversion (Complete)
- Converted 8 abort() calls to FATAL_CHECK
- Bounds checking for read/write operations
- Tests pass in all modes
### Phase 3: miniaudio_backend.cc Conversion (Complete)
- Converted 3 abort() calls to FATAL_*
- Callback re-entry detection (complex case using FATAL_CODE_BEGIN/END)
- Device validation and frameCount bounds checking
- Tests pass in all modes
### Phase 4: Codebase Analysis (Complete)
- Systematic search for all error patterns
- Verified no remaining abort() in production
- Identified graceful error handling (correct design)
- Found optional improvement opportunities
### Phase 5: Size Measurement (Complete)
- Built 3 configurations (Normal, STRIP_ALL, FINAL_STRIP)
- Measured full binary and all subsystem libraries
- Documented findings and insights
- Verified builds are functional
---
## Future Work
### Immediate Opportunities
1. **Expand to GPU subsystem** (estimated +2-3 KB savings)
- Pipeline validation checks
- Shader compilation error handling
- Resource allocation bounds checks
2. **Expand to 3D subsystem** (estimated +2-3 KB savings)
- BVH bounds checking
- Object transform validation
- Physics collision detection checks
3. **Expand to Procedural subsystem** (estimated +1-2 KB savings)
- Texture generation validation
- Perlin noise bounds checks
- Parameter range validation
**Total estimated additional savings**: 5-10 KB across all subsystems
### Optional Improvements
1. **Add FATAL_UNREACHABLE to switch statements**
- spectral_brush.cc ProfileType switch
- hybrid_3d_effect.cc camera preset switch
- Estimated impact: ~60 bytes total
2. **Audit all conditional checks**
- Search for implicit error conditions (e.g., division by zero guards)
- Convert safety checks to FATAL_CHECK pattern
- Estimated impact: 1-2 KB
### Long-Term Considerations
1. **Profile-Guided Optimization**
- Measure hot paths during typical demo run
- Prioritize FATAL_CHECK removal in critical loops
- May provide additional performance benefits
2. **Custom Allocator Error Handling**
- If replacing CRT (Phase 2: Size Optimization), consider FATAL_CHECK for malloc failures
- Current code uses standard malloc (assumes success)
---
## Recommendations
### For Development Workflow
1. **Default to Normal build**
```bash
cmake -S . -B build
cmake --build build
```
- Full diagnostics
- Command-line tools available
- Fastest iteration cycle
2. **Test with STRIP_ALL before release**
```bash
cmake -S . -B build_strip -DDEMO_STRIP_ALL=ON
cmake --build build_strip --target demo64k
```
- Verify demo works without command-line parsing
- Catch dependencies on debug features
- Validate error handling still works
3. **Use FINAL_STRIP for final release only**
```bash
./scripts/build_final.sh
# or
cd build && make final
```
- Maximum size optimization
- Deploy to production
- ⚠️ No error checking - thoroughly test first!
### For Code Maintenance
1. **Always use FATAL_* macros for new error checks**
- Don't add raw abort() calls
- Use FATAL_CHECK for validation
- Use FATAL_ERROR for impossible cases
2. **Document error handling decisions**
- If NOT using FATAL_*, explain why (intentional graceful degradation)
- Add comments for non-obvious error paths
3. **Verify both modes before committing**
```bash
# Build normal
cmake --build build
# Build FINAL_STRIP
cmake -S . -B build_final -DDEMO_FINAL_STRIP=ON
cmake --build build_final
```
- Ensure code compiles in both modes
- Prevents accidental dependencies on error checking
---
## Conclusion
### Mission Status: ✅ COMPLETE
**What We Built**:
- ✅ Comprehensive FINAL_STRIP infrastructure (fatal_error.h)
- ✅ 11 error checks converted in audio subsystem
- ✅ Three build configurations with clear use cases
- ✅ Automated build tools (scripts, CMake targets)
- ✅ Complete documentation (HOWTO.md, CONTRIBUTING.md)
- ✅ Systematic codebase analysis (Phase 4)
- ✅ Comprehensive size measurements (Phase 5)
**Size Impact**:
- Audio library: **35,680 bytes saved** (2.5% reduction)
- STRIP_ALL: 32,152 bytes (90%)
- FINAL_STRIP: 3,528 bytes (10%)
- Full binary: **30,864 bytes saved** (0.58% reduction)
- Primarily from STRIP_ALL
- FINAL_STRIP adds 48 bytes
**Was It Worth It?**
✅ **YES** - For a 64k demo, every byte matters:
- Infrastructure is reusable across entire codebase
- Establishes best practices for error checking
- Zero runtime cost when stripped
- Small source code footprint (fatal_error.h ~200 lines)
- Maintainable (self-documenting macros)
- Future expansion potential (5-10 KB estimated)
### Key Takeaways
1. **STRIP_ALL is the workhorse** - Provides 90% of size savings by removing debug infrastructure
2. **FINAL_STRIP is insurance** - Guarantees check removal even when compiler can't optimize automatically
3. **Defense-in-depth works** - Three build modes balance safety and optimization
4. **Infrastructure is production-ready** - Awaiting expansion to gpu, 3d, procedural subsystems
### Next Steps
1. **Expand to other subsystems** (recommended next task)
- Start with gpu subsystem (most critical)
- Then 3d subsystem (physics/collision checks)
- Finally procedural subsystem (generation validation)
2. **Optional: Add FATAL_UNREACHABLE** to exhaustive switches
- Low effort (~10 minutes)
- Small impact (~60 bytes)
- Good defensive programming
3. **Monitor size budget** as project grows
- Regularly build with FINAL_STRIP
- Track binary size over time
- Prioritize high-impact optimizations
---
**Report Generated**: February 7, 2026
**Author**: Claude Sonnet 4.5
**Status**: Production-Ready Infrastructure
|