diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-09 17:43:12 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-09 17:43:12 +0100 |
| commit | 4f51332be0ee1a046fdc03514d32fe31cf7b61a8 (patch) | |
| tree | cfcee2627be6b6af4185d24c5a0049f331b0c5d2 /doc/SIZE_MEASUREMENT.md | |
| parent | d5f78a4c2e7b626a492643efd62ddeb394276722 (diff) | |
docs: Update documentation and clean up obsolete files
- Add Task #76: External library size measurement
- Update hot-reload documentation across README, HOWTO, PROJECT_CONTEXT
- Update test count: 36/36 passing (100%)
- Remove completed analysis files from root
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'doc/SIZE_MEASUREMENT.md')
| -rw-r--r-- | doc/SIZE_MEASUREMENT.md | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/doc/SIZE_MEASUREMENT.md b/doc/SIZE_MEASUREMENT.md new file mode 100644 index 0000000..b997ea5 --- /dev/null +++ b/doc/SIZE_MEASUREMENT.md @@ -0,0 +1,341 @@ +# External Library Size Measurement (Task #76) + +## Goal + +Measure the true binary size of demo code vs external library overhead by stubbing out all system dependencies with minimal implementations. + +**Motivation:** Current STRIP_ALL builds include wgpu_native (~3-4MB), GLFW, and system libraries. We need to isolate core demo size to: +- Track size budget accurately +- Identify optimization targets +- Measure progress toward 64KB goal + +## Problem Statement + +Current size breakdown is opaque: +``` +STRIP_ALL build: ~5.1MB total +├── wgpu_native: ~3-4MB (estimate) +├── GLFW: ~500KB (estimate) +├── System libs: ~500KB (estimate) +└── Demo code: ??? KB (unknown) +``` + +**Goal:** Measure demo code size precisely by replacing external dependencies with stubs. + +## Approach + +Create `STRIP_EXTERNAL_LIBS` build mode: +- Replaces real libraries with minimal stub implementations +- Functions compile but do nothing (return nullptr, no-ops) +- Binary compiles successfully but **does not run** +- Purpose: Size measurement only + +## Architecture + +### Stub Implementations + +#### 1. wgpu_native Stubs (`third_party/stubs/wgpu_native.c`) + +Minimal WebGPU API implementation: +```c +// All functions return nullptr or void +WGPUInstance wgpuCreateInstance(const WGPUInstanceDescriptor* desc) { + (void)desc; + return (WGPUInstance)0; +} + +WGPUAdapter wgpuInstanceRequestAdapter(...) { + return (WGPUAdapter)0; +} + +// ~200 functions to stub +``` + +**Strategy:** +- Parse `webgpu.h` to generate stubs automatically +- All pointers return nullptr +- All numeric returns = 0 +- All void functions are empty + +#### 2. GLFW Stubs (`third_party/stubs/glfw3.c`) + +Window/input API stubs: +```c +int glfwInit(void) { return 1; } +void glfwTerminate(void) {} +GLFWwindow* glfwCreateWindow(...) { return (GLFWwindow*)0; } +void glfwPollEvents(void) {} +int glfwWindowShouldClose(GLFWwindow* w) { (void)w; return 0; } +// ~100 functions +``` + +#### 3. miniaudio Stubs (`third_party/stubs/miniaudio.c`) + +Audio backend stubs: +```c +ma_result ma_context_init(...) { return MA_SUCCESS; } +ma_result ma_device_init(...) { return MA_SUCCESS; } +ma_result ma_device_start(...) { return MA_SUCCESS; } +void ma_device_stop(...) {} +void ma_device_uninit(...) {} +// ~50 functions used by demo +``` + +#### 4. System Library Stubs + +**pthread:** +```c +int pthread_create(...) { return 0; } +int pthread_join(...) { return 0; } +int pthread_mutex_init(...) { return 0; } +// ~20 functions +``` + +**Math (libm):** +```c +double sin(double x) { (void)x; return 0.0; } +double cos(double x) { (void)x; return 0.0; } +float sinf(float x) { (void)x; return 0.0f; } +// ~30 functions +``` + +**Platform-specific (macOS):** +```c +// Stub Metal/Foundation/Cocoa frameworks +// Minimal Objective-C stubs if needed +``` + +### Build System Integration + +**CMakeLists.txt:** +```cmake +if(DEMO_STRIP_EXTERNAL_LIBS) + # Build stub libraries + add_library(wgpu_stub STATIC third_party/stubs/wgpu_native.c) + add_library(glfw_stub STATIC third_party/stubs/glfw3.c) + add_library(miniaudio_stub STATIC third_party/stubs/miniaudio.c) + add_library(system_stub STATIC third_party/stubs/system.c) + + # Override library targets + set(DEMO_LIBS wgpu_stub glfw_stub miniaudio_stub system_stub) + + # Minimal flags (no LTO to see unoptimized size) + set(CMAKE_C_FLAGS "-Os") + set(CMAKE_CXX_FLAGS "-Os") +endif() +``` + +**Build command:** +```bash +cmake -S . -B build_size -DDEMO_STRIP_EXTERNAL_LIBS=ON +cmake --build build_size -j4 +ls -lh build_size/demo64k # True demo size +``` + +## Implementation Plan + +### Phase 1: Stub Generation Tool + +**Script: `scripts/generate_stubs.py`** + +Parses header files and generates stub implementations: +```python +# Parse webgpu.h, glfw3.h, miniaudio.h +# Extract function signatures +# Generate minimal implementations +# Output to third_party/stubs/ +``` + +**Input:** Header files with annotations +**Output:** Complete stub .c files + +**Heuristics:** +- Pointer returns → nullptr +- Numeric returns → 0 +- Boolean returns → true/1 +- Void functions → empty body +- Enum returns → first enum value + +### Phase 2: Build System Integration + +1. Add `DEMO_STRIP_EXTERNAL_LIBS` option +2. Create stub library targets +3. Override `DEMO_LIBS` when flag enabled +4. Disable features requiring runtime (audio playback, window creation) + +### Phase 3: Compatibility Layer + +Some demo code expects valid objects. Add thin shims: + +**`src/platform/stub_platform.cc`:** +```cpp +#if defined(STRIP_EXTERNAL_LIBS) +// Override platform_init to skip GLFW +PlatformState platform_init(bool, int, int) { + PlatformState state = {}; + state.width = 1280; + state.height = 720; + return state; +} +#endif +``` + +**`src/audio/stub_audio.cc`:** +```cpp +#if defined(STRIP_EXTERNAL_LIBS) +// Override audio_init to skip miniaudio +void audio_init() {} +void audio_start() {} +#endif +``` + +### Phase 4: Validation + +Ensure binary compiles and links: +```bash +# Should compile successfully +cmake -S . -B build_size -DDEMO_STRIP_EXTERNAL_LIBS=ON +cmake --build build_size -j4 + +# Size measurement +ls -lh build_size/demo64k + +# Strip debug symbols +strip build_size/demo64k +ls -lh build_size/demo64k + +# Compare with real build +ls -lh build_strip/demo64k +``` + +## Expected Results + +**Size Breakdown (Projected):** +``` +Real STRIP_ALL build: 5.1 MB +├── wgpu_native: 3.5 MB (68%) +├── GLFW: 0.5 MB (10%) +├── System libs: 0.6 MB (12%) +└── Demo code: 0.5 MB (10%) + +STRIP_EXTERNAL_LIBS build: 0.5 MB +└── Demo code only: 0.5 MB (100%) +``` + +**Validation:** +- Binary compiles without errors +- All symbols resolve +- Size is significantly smaller (< 1MB) +- Binary does NOT run (expected) + +## Use Cases + +### 1. Size Budget Tracking +```bash +# Weekly measurement +./scripts/measure_size.sh +# Outputs: Demo=512KB, External=4.5MB +``` + +### 2. Optimization Targeting +Identify which subsystems contribute most to demo size: +- GPU effects: 150KB +- 3D rendering: 120KB +- Audio synthesis: 100KB +- Asset system: 80KB + +### 3. CI Integration +Track size growth over time: +```yaml +# .github/workflows/size_check.yml +- name: Measure demo size + run: | + cmake -B build_size -DDEMO_STRIP_EXTERNAL_LIBS=ON + size=$(stat -f%z build_size/demo64k) + echo "Demo size: $size bytes" +``` + +## Trade-offs + +### Pros +- Accurate size measurement +- Identifies optimization targets +- Simple implementation (stubs) +- No runtime required + +### Cons +- Maintenance burden (stubs must match real APIs) +- Binary doesn't run (testing impossible) +- Platform-specific stubbing (macOS frameworks complex) +- Stub generation tool needs maintenance + +### Alternative Approaches + +**1. Link-time size analysis:** +```bash +# Use linker map to attribute size +-Wl,-map,output.map +# Parse map file to see per-symbol sizes +``` +**Pro:** No stubs needed +**Con:** Complex parsing, less accurate + +**2. Binary diff analysis:** +```bash +# Build with/without each library +# Diff binary sizes +``` +**Pro:** Simpler +**Con:** Doesn't isolate demo code cleanly + +**3. Compiler size reports:** +```bash +-ffunction-sections -fdata-sections +-Wl,--print-gc-sections +``` +**Pro:** Built-in tooling +**Con:** Still includes external library overhead + +**Chosen:** Stub approach (most accurate, clear results) + +## Implementation Effort + +**Estimated time: 8-12 hours** + +- Phase 1: Stub generation (3-4 hours) +- Phase 2: Build integration (2-3 hours) +- Phase 3: Compatibility layer (2-3 hours) +- Phase 4: Validation & documentation (1-2 hours) + +**Priority:** Low (measurement tool, not critical for demo) + +## Success Criteria + +1. Binary compiles successfully with `STRIP_EXTERNAL_LIBS=ON` +2. Size < 1MB (proves external lib overhead is measured) +3. Repeatable builds produce consistent sizes +4. Can track size changes over time +5. Documentation clear for future use + +## Related Files + +**New files:** +- `third_party/stubs/wgpu_native.c` - WebGPU stubs (~200 functions) +- `third_party/stubs/glfw3.c` - GLFW stubs (~100 functions) +- `third_party/stubs/miniaudio.c` - Audio stubs (~50 functions) +- `third_party/stubs/system.c` - System library stubs (pthread, math) +- `scripts/generate_stubs.py` - Stub generation tool +- `scripts/measure_size.sh` - Size measurement script + +**Modified files:** +- `CMakeLists.txt` - Add STRIP_EXTERNAL_LIBS mode +- `src/platform/platform.cc` - Conditional stub overrides +- `src/audio/audio.cc` - Conditional stub overrides + +## Notes + +- This is a **measurement tool**, not a runtime mode +- Binary will not execute (all APIs stubbed) +- Useful for tracking optimization progress +- Can reveal surprising size contributors +- Platform-specific (stubs may differ on Windows/Linux/macOS) |
