Introducción
Si tu aplicación requiere timestamps con precisión de submicrosegundos y bajo overhead (ej: pipelines de 1–10μs por etapa, tracing distribuido con OpenTelemetry, o benchmarks de microarquitectura), el método estándar de Linux mediante clock_gettime() puede consumir entre el 40% y 60% de tu presupuesto de latencia por timestamp. En un escenario típico, cada llamada a now() en C++ invoca tres accesos a relojes distintos (REALTIME y MONOTONIC), cada uno enrutado a través de vDSO (Virtual Dynamic Shared Object), que aunque evita el syscall, aún introduce overhead por:
- Lectura secuencial de la data page compartida entre kernel y userspace.
- Protección con seqlock para sincronización.
- Cálculo de conversión de ciclos a nanosegundos en userspace.
Esta guía demuestra cómo reducir ese overhead un 30% usando directamente el Timestamp Counter (TSC) del CPU, evitando vDSO y manteniendo precisión sub-microsegundo. El enfoque es válido para kernels Linux ≥6.1 y CPUs x86 con TSC invariant (verificable con grep constant_tsc /proc/cpuinfo).
Qué es y para qué sirve
El problema: overhead oculto en timestamps estándar
El método convencional para obtener timestamps en Linux (vía std::chrono::steady_clock en C++ o System.currentTimeMillis() en Java) se apoya en clock_gettime(CLOCK_MONOTONIC, ...), que:
- No es un syscall real: la libc lo redirige a vDSO, que lee una estructura compartida (vdso_data) actualizada por el kernel en cada tick (tipicamente 1ms).
- Requiere cálculos en userspace: la conversión de ciclos TSC a nanosegundos se hace con multiplicadores (mult/shift) almacenados en la data page.
- Duplica trabajo: Para un span de tracing, necesitas tres timestamps (start realtime, monotonic start, monotonic end), multiplicando el overhead.
clock_gettime() mediante vDSO ronda 46–49ns, un presupuesto inviable para aplicaciones que requieran <100ns por timestamp.
La solución: usar TSC directamente
El Timestamp Counter (TSC) es un registro de 64 bits en el CPU que:
- Invariant TSC: No se detiene con C-states ni cambios de frecuencia (verificar con
grep nonstop_tsc /proc/cpuinfo). - Precisión de ciclos: La frecuencia base es típicamente 1–3GHz (ej: 3.0GHz = 0.33ns por ciclo).
- Sin overhead de vDSO: Leer TSC requiere solo la instrucción
rdtsc(ordtscppara serialización), sin accesos a memoria compartida.
- Use
rdtscppara leer TSC con serialización. - Convierta ciclos TSC a nanosegundos usando parámetros del kernel (obtenidos vía
/sys/devices/system/clocksource/clocksource0/current_clocksourcey/proc/cpuinfo). - Evite vDSO y syscalls.
Prerequisitos
| Componente | Versión/Configuración mínima | Cómo verificar |
|---|---|---|
| Kernel Linux | ≥6.1 (cambios en *vdso* desde 6.15) |