> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-postgresql-tls-support.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Perfilado de ClickHouse con XRay de LLVM

> Aprende a perfilar ClickHouse con el perfilador de instrumentación XRay de LLVM, visualizar trazas y analizar el rendimiento.

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

{frontMatter.description}

<div id="types-of-profilers">
  ## Tipos de profilers
</div>

LLVM ya incluye una herramienta que instrumenta el código y nos permite realizar [perfilado por instrumentación](https://en.wikipedia.org/wiki/Profiling_\(computer_programming\)#Instrumentation). A
diferencia del [muestreo o perfilado estadístico](https://en.wikipedia.org/wiki/Profiling_\(computer_programming\)#Statistical_profilers),
es muy preciso y no pierde ninguna llamada, a costa de tener que instrumentar el código y de
consumir más recursos.

En pocas palabras, un profiler por instrumentación introduce código nuevo para rastrear las llamadas a todas las funciones.
Los profilers estadísticos nos permiten ejecutar el código sin necesidad de hacer cambios, tomando instantáneas
periódicamente para ver el estado de la aplicación. Por lo tanto, solo se tienen en cuenta las funciones que se están ejecutando cuando se toma la instantánea.
[perf](https://en.wikipedia.org/wiki/Perf_%28Linux%29) es un profiler estadístico muy conocido.

<div id="profiling-clickhouse-using-xray-integration">
  ## Perfilado de ClickHouse con la integración de XRay
</div>

En ClickHouse 25.12, XRay viene integrado para añadir de forma transparente nuevos puntos de instrumentación a las funciones.
Así, cualquier versión oficial ya incluye esta funcionalidad, que puede activarse bajo demanda sin
afectar al rendimiento general cuando no está habilitada. La idea es habilitar el menor número posible de
puntos de instrumentación para obtener información valiosa.

Podemos añadir un nuevo punto de instrumentación de perfil mediante la
sentencia [SYSTEM INSTRUMENT ADD
PROFILE](/es/reference/statements/system#instrument-add-profile).
Las funciones que se van a instrumentar pueden obtenerse de la
tabla del sistema [system.symbols](/es/reference/system-tables/symbols). Supongamos que
queremos perfilar la función `sleepForNanoseconds`, que es una función práctica para comprobar cuánto
tarda en ejecutarse.

```sql theme={null}
SYSTEM INSTRUMENT ADD 'sleepForNanoseconds' PROFILE
```

Luego, lo dejamos en ejecución durante el tiempo que queramos perfilar y lo detenemos.

```sql theme={null}
SYSTEM INSTRUMENT REMOVE ALL
```

Convertimos los datos recopilados en system.trace\_log [al formato de Chrome](/es/reference/system-tables/trace_log#chrome-event-trace-format) para
visualizarlos en [Perfetto](https://ui.perfetto.dev). Observe el query\_id, cpu\_id y la traza de pila de
cada registro.

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/qtP2oqNQEVmSy5Lz/images/knowledgebase/profiling-clickhouse-with-llvm-xray/profile.webp?fit=max&auto=format&n=qtP2oqNQEVmSy5Lz&q=85&s=d736d2696e487c8e0cf654ccf5dbb746" size="md" alt="orden temporal" width="3646" height="1894" data-path="images/knowledgebase/profiling-clickhouse-with-llvm-xray/profile.webp" />

<div id="profiling-a-native-application-using-xray">
  ## Perfilado de una aplicación nativa con XRay
</div>

La siguiente sección se incluye como referencia para comprender cómo funciona XRay internamente y cómo puede
utilizarse sin configuración adicional para perfilar una aplicación nativa.

<div id="instrument-the-code">
  ### Instrumentar el código
</div>

Supongamos el siguiente código fuente:

```cpp theme={null}
#include <chrono>
#include <cstdio>
#include <thread>

void one()
{
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

void two()
{
    std::this_thread::sleep_for(std::chrono::milliseconds(5));
}

int main()
{
    printf("Start\n");

    for (int i = 0; i < 10; ++i)
    {
        one();
        two();
    }

    printf("Finish\n");
}
```

Para instrumentar con XRay, debemos añadir algunas opciones como estas:

```bash theme={null}
clang++ -o test test.cpp -fxray-instrument -fxray-instruction-threshold=1
```

* `-fxray-instrument` es necesario para instrumentar el código.
* `-fxray-instruction-threshold=1` se usa para instrumentar todas las funciones, aunque sean
  muy pequeñas, como en nuestro ejemplo. De forma predeterminada, instrumenta las funciones con [al menos 200
  instrucciones](https://llvm.org/docs/XRay.html#instrumenting-your-c-c-objective-c-application).

Podemos comprobar que el código se ha instrumentado correctamente verificando que hay una nueva sección en el
binario:

```bash theme={null}
objdump -h -j xray_instr_map test

test:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
 17 xray_instr_map 000005c0  000000000002f91c  000000000002f91c  0002f91c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
```

<div id="run-the-process-with-proper-env-var-values-to-collect-the-trace">
  ### Ejecutar el proceso con los valores adecuados de las variables de entorno para recopilar la traza
</div>

De forma predeterminada, no se recopilan datos del profiler a menos que se solicite explícitamente. En otras palabras, salvo que
estemos haciendo perfilado, la sobrecarga es insignificante. Podemos establecer distintos valores para `XRAY_OPTIONS` para
configurar cuándo el profiler empieza a recopilar datos y cómo lo hace.

```bash theme={null}
XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic verbosity=1" ./test
==74394==XRay: Log file in 'xray-log.test.14imlN'
Start
Finish
==74394==Cleaned up log for TID: 74394
```

<div id="convert-the-trace">
  ### Convertir la traza
</div>

Las trazas de XRay se pueden convertir a varios formatos. El formato `trace_event` es muy útil porque
es fácil de analizar y ya existen varias herramientas compatibles con él, así que usaremos ese:

```bash theme={null}
llvm-xray convert --symbolize --instr_map=./test --output-format=trace_event xray-log.test.14imlN | gzip > test-trace.txt.gz
```

<div id="visualize-the-trace">
  ### Visualiza la traza
</div>

Podemos usar interfaces web como [speedscope.app](https://www.speedscope.app/) o
[Perfetto](https://ui.perfetto.dev).

Aunque Perfetto facilita la visualización de varios hilos y la realización de consultas sobre los datos, speedscope es mejor
para generar un flamegraph y una vista tipo sándwich de tus datos.

<div id="time-order">
  #### Orden cronológico
</div>

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/qtP2oqNQEVmSy5Lz/images/knowledgebase/profiling-clickhouse-with-llvm-xray/time-order.webp?fit=max&auto=format&n=qtP2oqNQEVmSy5Lz&q=85&s=05b2874649ef98a372c935fa5189773a" size="md" alt="time-order" width="3227" height="422" data-path="images/knowledgebase/profiling-clickhouse-with-llvm-xray/time-order.webp" />

<div id="left-heavy">
  #### Cargado a la izquierda
</div>

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/qtP2oqNQEVmSy5Lz/images/knowledgebase/profiling-clickhouse-with-llvm-xray/left-heavy.webp?fit=max&auto=format&n=qtP2oqNQEVmSy5Lz&q=85&s=1137c508869e56b2abaabf4445f332e0" size="md" alt="cargado a la izquierda" width="3233" height="415" data-path="images/knowledgebase/profiling-clickhouse-with-llvm-xray/left-heavy.webp" />

<div id="sandwitch">
  #### Sándwich
</div>

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/qtP2oqNQEVmSy5Lz/images/knowledgebase/profiling-clickhouse-with-llvm-xray/sandwich.webp?fit=max&auto=format&n=qtP2oqNQEVmSy5Lz&q=85&s=8467717652443b93a71d0377ac58d60d" size="md" alt="sándwich" width="3228" height="256" data-path="images/knowledgebase/profiling-clickhouse-with-llvm-xray/sandwich.webp" />

<div id="check-out-the-docs">
  ## Consulta la documentación
</div>

* [SYSTEM INSTRUMENT](/es/reference/statements/system#instrument) — Añade
  o elimina puntos de instrumentación.
* [system.instrumentation](/es/reference/system-tables/instrumentation)
  — Inspecciona los puntos instrumentados.
* [system.symbols](/es/reference/system-tables/symbols) — Inspecciona
  los símbolos para añadir puntos de instrumentación.
* [system.trace\_log](/es/reference/system-tables/trace_log) — Inspecciona los datos
  recopilados mediante puntos de instrumentación.
* [XRay Instrumentation](https://llvm.org/docs/XRay.html)
* Documentación de [Debugging with XRay](https://llvm.org/docs/XRayExample.html) para obtener más información.
