Tracy Profiler - Perfilador de Frames en Tiempo Real Hoja de Trucos
Tracy es un perfilador híbrido de frame y muestreo en tiempo real de resolución de nanosegundos, ampliamente utilizado en videojuegos y C++ y Rust de baja latencia. Añades macros de zona ligeros a tu código, y Tracy transmite datos de temporización en vivo a una UI de escritorio donde puedes ver cada frame, cada zona, tiempos de GPU, asignaciones de memoria y contención de bloqueos mientras el programa se ejecuta. Su combinación de instrumentación manual más muestreo automático da tanto zonas semánticas precisas como puntos calientes no atribuidos.
Instalación
| Componente | Cómo |
|---|
| Servidor (UI) | Construir profiler/ desde el repo o descargar release |
| Cliente (librería) | Agregar TracyClient.cpp + headers a tu compilación |
| Rust | cargo add tracy-client (o tracing-tracy) |
| Habilitar | Compilar con TRACY_ENABLE definido |
| Verificar | Lanzar la UI; espera una conexión de cliente |
Instrumentando C++
#include "tracy/Tracy.hpp"
void update() {
ZoneScoped; // zona nombrada después de la función
physics();
}
void render() {
ZoneScopedN("Render Pass"); // nombre explícito
ZoneColor(0x00FF00);
draw();
}
int main() {
while (running) {
update();
render();
FrameMark; // marca límite de frame
}
}
| Macro | Propósito |
|---|
ZoneScoped | Temporizar el scope envolvente |
ZoneScopedN("name") | Zona nombrada |
ZoneText(str, len) | Adjuntar texto a una zona |
FrameMark | Delimitar frames |
TracyPlot("fps", v) | Graficar un valor numérico sobre tiempo |
TracyMessage(...) | Log un mensaje en la timeline |
TracyLockable(...) | Rastrear contención de un mutex |
Instrumentando Rust
use tracy_client::{Client, span};
fn main() {
let _client = Client::start();
loop {
{
let _s = span!("update");
update();
}
tracy_client::frame_mark();
}
}
O conéctalo a tracing con el crate tracing-tracy para que los spans existentes aparezcan en Tracy automáticamente.
Memoria y GPU
| Característica | Cómo |
|---|
| Rastreo de asignación | TracyAlloc(ptr, size) / TracyFree(ptr) |
| Asignadores personalizados | Envolver alloc/free con los macros |
| Zonas de GPU (Vulkan/D3D/OpenGL) | TracyVkZone, TracyD3D12Zone, etc. |
| Contexto de GPU | Crear una vez, luego las zonas se adjuntan |
La UI
| Vista | Muestra |
|---|
| Timeline | Zonas por thread, frame por frame |
| Estadísticas | Tiempo agregado por zona |
| Encontrar zona | Histograma de duraciones de una zona |
| Comparar | Diff dos capturas (antes/después de cambio) |
| Memoria | Timeline de asignación y leaks |
| Bloqueos | Contención entre threads |
| Flame graph | Estructura de llamada agregada |
Flujo de Trabajo: Persiguiendo un Spike de Frame
| Paso | Acción |
|---|
| 1 | Ejecutar con cliente conectado; reproducir el hitch |
| 2 | Encontrar el frame largo en la timeline |
| 3 | Zoom dentro — ¿qué zona domina? |
| 4 | Abrir “Find Zone” para esa zona → histograma de duración |
| 5 | Verificar contexto del outlier (bloqueos, asignaciones, espera GPU) |
| 6 | Arreglar, capturar de nuevo, usar Compare para probar la mejora |
Ese flujo de trabajo de comparar-dos-capturas es una de las características más prácticas de Tracy — convierte “se siente más rápido” en un delta medido.
Modo de Muestreo
Más allá de zonas manuales, Tracy puede muestrear stacks de llamadas automáticamente (Linux/Windows), atrapando tiempo en código que no instrumentaste. Combina ambos: las zonas dan estructura semántica, el muestreo llena los gaps.
Tracy vs Perfiladores Relacionados
| Aspecto | Tracy | perf | Perfetto |
|---|
| Modelo | Zonas instrumentadas + muestreo | Muestreo | Timeline de sistema |
| Resolución | Nanosegundo | Intervalo de muestra | Nivel de evento |
| Vista en vivo | Sí (en tiempo real) | No | Post-hoc |
| Soporte GPU | Integrado | No | Parcial |
| Mejor para | Videojuegos, basado en frames, C++/Rust de baja latencia | Caminos calientes CPU | Timelines de sistema completo |
Complementa perf y Perfetto; la ventaja de Tracy es perfilado vivo, orientado a frames e instrumentado.
Recursos