diff --git a/CLAUDE.md b/CLAUDE.md index a299348..7843cbc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -367,6 +367,32 @@ pub const MacroPlayer = struct { --- +## OPTIMIZACIONES DE RENDIMIENTO (2026-01-03) + +### Optimizaciones Activas ✅ + +| Optimización | Archivo | Descripción | +|--------------|---------|-------------| +| **Turbo Píxeles** | `render/framebuffer.zig:117` | `@setRuntimeSafety(false)` en `fillRect` - elimina bounds checks en hot path | +| **Fast Path Texto** | `render/ttf.zig:323,375` | Escritura directa para píxeles opacos (alpha==255), evita blend innecesario | + +### Optimización Probada y Revertida ❌ + +| Optimización | Problema | Alternativa | +|--------------|----------|-------------| +| **Burst Suppression** (auto-gestión de estrés) | Causaba paneles vacíos durante navegación rápida | El debounce en DataManager ya evita queries excesivas | + +**Detalles del Burst Suppression:** +- Concepto: suprimir dibujo de paneles durante ráfagas de navegación (<100ms) +- Implementación: `if (!frame_result.should_draw) return;` en paneles +- Problema: el frame se dibujaba vacío (solo fondo), sin widgets +- Causa raíz: suprimía TODO el dibujo, no solo las queries BD +- Lección: el debounce a nivel DataManager es más elegante + +**Pendiente verificar:** Mensajes continuos de redraw en idle (posible bug en animaciones). + +--- + ## NOTAS ZIG 0.15.2 ```zig diff --git a/src/core/context.zig b/src/core/context.zig index a583805..c463f91 100644 --- a/src/core/context.zig +++ b/src/core/context.zig @@ -149,8 +149,10 @@ pub const Context = struct { /// Frame statistics for performance monitoring pub const FrameStats = struct { - /// Number of commands this frame + /// Number of commands generated this frame command_count: usize = 0, + /// Number of commands actually executed (set by renderer) + executed_cmds: usize = 0, /// Number of widgets drawn widget_count: usize = 0, /// Arena bytes used this frame @@ -231,6 +233,7 @@ pub const Context = struct { // Reset frame stats self.stats.command_count = 0; + self.stats.executed_cmds = 0; self.stats.widget_count = 0; self.stats.arena_bytes = 0; self.stats.dirty_rect_count = 0; diff --git a/src/render/software.zig b/src/render/software.zig index 03a1f77..412a574 100644 --- a/src/render/software.zig +++ b/src/render/software.zig @@ -323,6 +323,9 @@ pub const SoftwareRenderer = struct { /// Shadow cache for instant shadow blitting (optional, requires allocator) shadow_cache: ?ShadowCache = null, + /// Counter of actually executed commands (for telemetry) + executed_count: usize = 0, + const Self = @This(); /// Initialize the renderer (without shadow cache) @@ -382,6 +385,7 @@ pub const SoftwareRenderer = struct { /// Execute a single draw command pub fn execute(self: *Self, cmd: DrawCommand) void { + self.executed_count += 1; switch (cmd) { .rect => |r| self.drawRect(r), .rounded_rect => |r| self.drawRoundedRect(r), @@ -399,6 +403,16 @@ pub const SoftwareRenderer = struct { } } + /// Reset executed command counter (call at start of frame) + pub fn resetExecutedCount(self: *Self) void { + self.executed_count = 0; + } + + /// Get number of commands executed since last reset + pub fn getExecutedCount(self: Self) usize { + return self.executed_count; + } + /// Execute all commands in a list pub fn executeAll(self: *Self, commands: []const DrawCommand) void { for (commands) |cmd| {