perf(telemetry): Añadir métrica executed_cmds
- FrameStats: nuevo campo executed_cmds para comandos realmente ejecutados - SoftwareRenderer: contador que se incrementa en execute() - Métodos resetExecutedCount() y getExecutedCount() - CLAUDE.md: sección OPTIMIZACIONES DE RENDIMIENTO documentada Permite comparar Total (generados) vs Exec (ejecutados) para diagnosticar efectividad del dirty regions filtering. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4ce39c4fc8
commit
f4b1b75914
3 changed files with 44 additions and 1 deletions
26
CLAUDE.md
26
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
|
## NOTAS ZIG 0.15.2
|
||||||
|
|
||||||
```zig
|
```zig
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,10 @@ pub const Context = struct {
|
||||||
|
|
||||||
/// Frame statistics for performance monitoring
|
/// Frame statistics for performance monitoring
|
||||||
pub const FrameStats = struct {
|
pub const FrameStats = struct {
|
||||||
/// Number of commands this frame
|
/// Number of commands generated this frame
|
||||||
command_count: usize = 0,
|
command_count: usize = 0,
|
||||||
|
/// Number of commands actually executed (set by renderer)
|
||||||
|
executed_cmds: usize = 0,
|
||||||
/// Number of widgets drawn
|
/// Number of widgets drawn
|
||||||
widget_count: usize = 0,
|
widget_count: usize = 0,
|
||||||
/// Arena bytes used this frame
|
/// Arena bytes used this frame
|
||||||
|
|
@ -231,6 +233,7 @@ pub const Context = struct {
|
||||||
|
|
||||||
// Reset frame stats
|
// Reset frame stats
|
||||||
self.stats.command_count = 0;
|
self.stats.command_count = 0;
|
||||||
|
self.stats.executed_cmds = 0;
|
||||||
self.stats.widget_count = 0;
|
self.stats.widget_count = 0;
|
||||||
self.stats.arena_bytes = 0;
|
self.stats.arena_bytes = 0;
|
||||||
self.stats.dirty_rect_count = 0;
|
self.stats.dirty_rect_count = 0;
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,9 @@ pub const SoftwareRenderer = struct {
|
||||||
/// Shadow cache for instant shadow blitting (optional, requires allocator)
|
/// Shadow cache for instant shadow blitting (optional, requires allocator)
|
||||||
shadow_cache: ?ShadowCache = null,
|
shadow_cache: ?ShadowCache = null,
|
||||||
|
|
||||||
|
/// Counter of actually executed commands (for telemetry)
|
||||||
|
executed_count: usize = 0,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
/// Initialize the renderer (without shadow cache)
|
/// Initialize the renderer (without shadow cache)
|
||||||
|
|
@ -382,6 +385,7 @@ pub const SoftwareRenderer = struct {
|
||||||
|
|
||||||
/// Execute a single draw command
|
/// Execute a single draw command
|
||||||
pub fn execute(self: *Self, cmd: DrawCommand) void {
|
pub fn execute(self: *Self, cmd: DrawCommand) void {
|
||||||
|
self.executed_count += 1;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
.rect => |r| self.drawRect(r),
|
.rect => |r| self.drawRect(r),
|
||||||
.rounded_rect => |r| self.drawRoundedRect(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
|
/// Execute all commands in a list
|
||||||
pub fn executeAll(self: *Self, commands: []const DrawCommand) void {
|
pub fn executeAll(self: *Self, commands: []const DrawCommand) void {
|
||||||
for (commands) |cmd| {
|
for (commands) |cmd| {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue