> For the complete documentation index, see [llms.txt](https://doc.velneo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://doc.velneo.com/38/velneo-vdevelop/depuracion/perfilador-jerarquico-para-vclient-y-vserver.md).

# Perfilador jerárquico para vClient y vServer

El *profiler* (perfilador) de Velneo permite medir **cuánto tiempo se invierte en cada objeto de la solución** durante la ejecución de una aplicación, tanto en Velneo vClient como en Velneo vServer, para localizar los puntos de una aplicación que penalizan el rendimiento.

Es un *profiler* **jerárquico**: no solo indica cuánto tarda cada proceso, función o fórmula, sino también desde dónde se ha llamado y qué parte de su tiempo se ha ido en los objetos que a su vez ejecuta (subprocesos, fórmulas, comandos enviados al servidor, búsquedas, escrituras en disco, etc.).

El resultado se guarda en un fichero JSON que podemos analizar con la extensión Perfilador de Velneo vDevelop o con herramientas estándar como [Perfetto](https://ui.perfetto.dev/) o `chrome://tracing` del navegador Chrome.

{% hint style="info" %}
Cuando el *profiler* está desactivado, su impacto en el rendimiento es prácticamente nulo. Cuando está activado, añade un pequeño coste (del orden de 100 a 300 nanosegundos) a cada medición, por lo que las operaciones de duración inferior a un microsegundo, como fórmulas muy simples, aparecerán con tiempos ligeramente superiores a los reales.
{% endhint %}

## Qué mide

<table data-search="false"><thead><tr><th>Categoría</th><th>Qué mide</th><th>Dónde</th></tr></thead><tbody><tr><td><strong>Proceso</strong></td><td>Ejecución completa de un proceso.</td><td>Cliente y servidor</td></tr><tr><td><strong>Subproceso</strong></td><td>Bloques internos de un proceso.</td><td>Cliente y servidor</td></tr><tr><td><strong>Evento</strong></td><td>Ejecución de un manejador de evento.</td><td>Cliente y servidor</td></tr><tr><td><strong>JS</strong></td><td>Ejecución de un proceso o script JavaScript.</td><td>Cliente y servidor</td></tr><tr><td><strong>Función</strong></td><td>Ejecución de una función de la solución.</td><td>Cliente y servidor</td></tr><tr><td><strong>Fórmula</strong></td><td>Evaluación de cualquier fórmula, tanto clásica como JavaScript.</td><td>Cliente y servidor</td></tr><tr><td><strong>VATP WAIT</strong></td><td>Tiempo que el cliente espera la respuesta del servidor a cada comando del protocolo VATPS (incluye red y ejecución en el servidor).</td><td>Cliente</td></tr><tr><td><strong>VATP CMD</strong></td><td>Tiempo de ejecución en el servidor de cada comando VATPS recibido de un cliente.</td><td>Servidor</td></tr><tr><td><strong>Disco</strong></td><td>Alta, modificación y baja de registros.</td><td>Servidor</td></tr><tr><td><strong>Búsqueda</strong></td><td>Búsquedas en tablas (por índice, entre límites, por palabras, por trozos, tabla completa).</td><td>Servidor</td></tr></tbody></table>

El nombre de cada elemento permite localizar el objeto en Velneo vDevelop:

* Procesos, funciones y JavaScript: `alias_proyecto/nombre del objeto`.
* Eventos: `alias_proyecto/identificador del manejador`.
* Disco: `Alta`, `Modificar` o `Eliminar` seguido de `alias_proyecto/tabla`.
* Búsquedas: tipo de búsqueda seguido de `alias_proyecto/tabla`.
* Fórmulas: los primeros 80 caracteres de la fórmula.
* Comandos VATPS: descripción del comando (la misma que muestra el [Monitor de vClient](/38/velneo-vdevelop/depuracion/monitor-de-vclient.md)).

La información se recoge **por hilo de ejecución**, por lo que se miden todos los planos de ejecución: primer y segundo plano en Velneo vClient y tercer y cuarto plano en Velneo vServer.

{% hint style="warning" %}
El *profiler* de Velneo vClient y el de Velneo vServer son independientes: activarlo en uno no lo activa en el otro. Para analizar a la vez lo que sucede en el cliente y en el servidor hay que activarlo en ambos.

En Velneo vServer, el *profiler* registra la actividad de **todo el servidor** (todas las instancias, usuarios y enganches).
{% endhint %}

## Permisos

* **Velneo vClient**: el *profiler* solo se activa si el grupo del usuario conectado tiene permiso de **edición** sobre la solución de la instancia. Si no lo tiene, se ignora y se registra el mensaje *"Profiler ignorado: el grupo del usuario no tiene permiso de edición sobre el sitio"*.
* **Velneo vServer** (línea de comandos y comandos de servicio): lo decide el administrador del servidor; no requiere usuario.
* **Funciones JavaScript**: ver Desde JavaScript.

## Cómo activarlo

#### Parámetro de línea de comandos /profiler

Tanto Velneo vClient como Velneo vServer admiten el parámetro:

```
/profiler
/profiler=opción=valor,opción=valor,...
```

Sin opciones, se activa con los valores por defecto. Las opciones se separan con coma (`,`) o punto y coma (`;`). Recomendamos usar la coma, ya que el punto y coma es separador de órdenes en las consolas de Windows PowerShell, Linux y macOS y obliga a entrecomillar el parámetro. Las rutas de fichero que contengan espacios deben ir siempre entre comillas. Los nombres de las opciones no distinguen mayúsculas de minúsculas.

En Velneo vClient el *profiler* se activa una vez identificado el usuario y comprobado su permiso. Una reconexión no reinicia la traza.

### Tabla de opciones

<table data-search="false"><thead><tr><th>Opción</th><th>Valores</th><th>Por defecto</th><th>Descripción</th></tr></thead><tbody><tr><td><code>mode</code></td><td><code>aggregate</code> | <code>timeline</code></td><td><code>aggregate</code></td><td><code>aggregate</code> acumula el tiempo y el número de llamadas de cada elemento; es ligero y adecuado para sesiones largas, y responde a la pregunta <em>¿qué es lo que más tarda?</em>. <code>timeline</code> registra cada ejecución con su momento real de inicio y su duración; es necesario para ver la línea temporal y para relacionar cliente y servidor.</td></tr><tr><td><code>interval</code></td><td>segundos</td><td><code>0</code></td><td>Si es mayor que 0, guarda el fichero periódicamente cada N segundos. Con <code>0</code> solo se guarda al terminar o cuando se solicite.</td></tr><tr><td><code>file</code></td><td>ruta de fichero</td><td>—</td><td>Ruta fija del fichero JSON. Cada guardado sobrescribe el mismo fichero.</td></tr><tr><td><code>dir</code></td><td>ruta de carpeta</td><td>—</td><td>Carpeta en la que se crea un fichero nuevo <code>profiler_AAAAMMDD_HHMMSS.json</code> en cada guardado.</td></tr><tr><td><code>format</code></td><td><code>combined</code> | <code>trace</code> | <code>gprof</code></td><td><code>combined</code></td><td><code>combined</code>: informe de texto y eventos. <code>trace</code>: solo eventos (fichero más ligero). <code>gprof</code>: solo informe de texto (no se puede abrir con el Perfilador ni con Perfetto).</td></tr><tr><td><code>level</code></td><td><code>1</code> | <code>0</code></td><td><code>1</code></td><td>Nivel de detalle. Con <code>1</code> se ocultan los subprocesos y se enmascaran los literales de las fórmulas (ver nivel de detalle y privacidad). Con <code>0</code> se muestra todo.</td></tr><tr><td><code>maxEvents</code></td><td>número entero</td><td><code>1000000</code></td><td>Solo en modo <code>timeline</code>: número máximo de eventos que se conservan por hilo. Al alcanzarlo se descartan los más antiguos. Cada evento ocupa unos 48 bytes de memoria.</td></tr><tr><td><code>open</code></td><td><code>0</code></td><td>se abre</td><td>Tras el primer guardado, en ejecución interactiva, se abre el fichero (o su carpeta, si el guardado es periódico) con la aplicación asociada del sistema. Con <code>open=0</code> no se abre.</td></tr></tbody></table>

Si se especifican tanto `file` como `dir`, prevalece `file`. Las opciones desconocidas o con valores numéricos incorrectos se ignoran, sin interrumpir el arranque.

### Carpeta por defecto

Si no se indica `file` ni `dir`, los ficheros se guardan con el nombre `profiler_AAAAMMDD_HHMMSS.json` en:

* **Velneo vClient**: `<carpeta del usuario>/Velneo/client/logs/profiler/`.
* **Velneo vServer**: `<carpeta del usuario que ejecuta vServer>/Velneo/server/logs/profiler/`.
* **Velneo vDevelop y Velneo vAdmin** (scripts): carpeta del usuario.
* **Velneo vClient Web**: el navegador descarga el fichero.

### Cuándo se guarda el fichero

* Al cerrar Velneo vClient o al detener Velneo vServer, si el *profiler* está activo.
* Periódicamente, si se ha indicado la opción `interval`. Cada guardado contiene **todo lo acumulado desde el inicio** de la sesión de perfilado. Si no ha habido actividad desde el último guardado, no se genera fichero.
* En Velneo vClient, al pulsar **Ctrl + F12** (solo si se ejecutó con `/profiler`). Tras guardar, se reinicia la traza.
* Al usar el comando de servicio `-c 41` de Velneo vServer.
* Al ejecutar la función JavaScript profilerDumpToFile.

{% hint style="info" %}
Si la aplicación no responde a **Ctrl + F12**, es posible que la propia solución tenga esa combinación de teclas reservada para otra acción. Conviene evitar en nuestras aplicaciones aceleradores con esa combinación si queremos poder usar el *profiler*.
{% endhint %}

### Comandos de servicio de Velneo vServer

Permiten iniciar y detener el *profiler* de un Velneo vServer en ejecución, sin reiniciarlo:

* `vServer -c 40`: inicia el *profiler* con las opciones por defecto. No hace nada si ya está activo. Se registra el mensaje *"Profiler iniciado. Destino: ruta"*. No admite opciones: para iniciarlo en modo `timeline` u otras opciones, hay que usar el parámetro `/profiler` al arrancar Velneo vServer o la función JavaScript `profilerSetOptions`.
* `vServer -c 41`: detiene el *profiler* y guarda el fichero. Se registra el mensaje *"Profiler guardado en: ruta"*.

### Desde JavaScript

La clase [VApp](/38/velneo-vdevelop/scripts/lenguajes/javascript/clases/vapp.md#de-profiler-jerarquico) dispone de funciones para controlar el *profiler* desde un proceso JavaScript. Es la forma de perfilar en Velneo Cloud, donde no se pueden pasar parámetros a Velneo vServer.

```javascript
// Medir una operación concreta y guardar el resultado en un fichero
theApp.profilerSetOptions("mode=timeline,file=C:/tmp/perf.json");
// ... operación a medir ...
theApp.profilerDumpToFile();
theApp.profilerSetEnabled(false);
```

Permisos necesarios según el lugar de ejecución:

* **Velneo vClient** (primer y segundo plano): puede perfilar si el grupo del usuario tiene permiso de edición sobre la solución, y puede usar `file` y `dir`.
* **Velneo vServer** (tercer y cuarto plano): puede perfilar si el usuario del enganche tiene permiso de edición sobre la solución. Solo puede usar `file` y `dir` si el usuario es supervisor; si no, se ignoran y se usa la carpeta por defecto.
* **Velneo vDevelop y Velneo vAdmin**: siempre.

Si no se tiene permiso, las funciones que activan el perfilador no hacen nada y se registra el mensaje *"Profiler ignorado: …"* en el log. Desactivarlo con `profilerSetEnabled(false)` no requiere permiso.

## Ejemplos de uso

```bash
# Diagnóstico rápido en vClient
vClient.exe vatps://usuario@servidor:690/aplicacion /profiler

# Línea temporal, a un fichero concreto, con guardado cada 10 segundos
vClient.exe vatps://usuario@servidor:690/aplicacion /profiler=mode=timeline,interval=10,file=C:\tmp\traza.json

# vServer: arranque con guardado periódico cada 60 segundos
vServer.exe -exec /profiler=mode=timeline,interval=60

# vServer en caliente, sin reiniciar el servicio
vServer.exe -c 40        # empezar a medir
#   ... reproducir la operación lenta desde un cliente conectado ...
vServer.exe -c 41        # detener y guardar en logs/profiler/profiler_*.json

# Comparar cliente y servidor en el tiempo (timeline en ambos extremos)
vServer.exe -exec /profiler=mode=timeline
vClient.exe vatps://usuario@servidor:690/aplicacion /profiler=mode=timeline

# Solo informe de texto legible (gprof), sin traza para Perfetto
vClient.exe vatps://usuario@servidor:690/aplicacion /profiler=format=gprof
```

## Nivel de detalle y privacidad

Con el nivel por defecto (`level=1`):

* Se ocultan los subprocesos; su tiempo se atribuye al proceso que los contiene.
* Se **enmascaran los literales de las fórmulas**: los textos entre comillas se sustituyen por `"?"` y los números por `?`. Los nombres de campos y variables se conservan. Por ejemplo, `jsonAddToObject(JSON_SES,"globalVar_CUR_USR_ID",#ID)` se muestra como `jsonAddToObject(JSON_SES,"?",#ID)`.
* La VRL se guarda sin usuario, contraseña ni parámetros.

Con `level=0` se muestra toda la información sin enmascarar. La contraseña no se guarda nunca.

{% hint style="info" %}
Si tenemos que enviar un fichero del *profiler* a terceros (por ejemplo, al soporte de Velneo), recomendamos generarlo con el nivel por defecto (`level=1`).
{% endhint %}

## Formato del fichero

El fichero generado es un JSON compatible con el formato *Trace Event* de Chrome, por lo que puede abrirse directamente en [Perfetto](https://ui.perfetto.dev/) o en `chrome://tracing`, además de en la extensión Perfilador.

```json
{
  "displayTimeUnit": "ms",
  "reportMetadata": {
    "app": "vClient",
    "version": "38.0.0",
    "platform": "Windows",
    "reportTime": "2026-10-28T10:15:02",
    "mode": "timeline",
    "level": 1,
    "monotonicEpochUsAtFirstScope": 1793180102000000,
    "vrl": "vatps://miservidor:690/MI_INSTANCIA"
  },
  "reportText": [
    "=== Velneo Profiler - Resultados ===",
    "..."
  ],
  "traceEvents": [
    {"name":"thread_name","ph":"M","pid":4321,"tid":1,"args":{"name":"Main Thread"}},
    {"name":"miapp/Refrescar totales","cat":"PROCESS","ph":"X","ts":1520.000,"dur":84211.500,"pid":4321,"tid":1,"args":{"calls":1,"id":"REFRESCAR_TOTALES"}}
  ]
}
```

### reportMetadata

* `app`: componente que generó el fichero (vClient, vServer…).
* `version`: versión de Velneo.
* `platform`: plataforma (Windows, macOS, Linux, iOS, Android o WASM / Browser).
* `reportTime`: fecha y hora local del guardado.
* `mode`, `level`: opciones con las que se generó.
* `monotonicEpochUsAtFirstScope`: instante, en microsegundos desde el 1/1/1970, de la primera medición. La hora real de un evento es este valor más su `ts`. Permite alinear las trazas de cliente y servidor.
* `vrl`: VRL de conexión (solo Velneo vClient).
* `completedThreadsDropped`: solo aparece si se han descartado hilos (se conservan como máximo 1024 hilos finalizados).
* `timelineEventsDropped`: solo aparece si se han descartado eventos por superar `maxEvents`. Indica que la traza está incompleta.

### reportText

Informe de texto, siempre agregado, con un perfil plano (porcentaje de tiempo, tiempo acumulado, tiempo propio, llamadas y tiempo medio por llamada de cada elemento) y un grafo de llamadas (padres e hijos de cada elemento) por cada hilo. No se incluye si `format=trace`.

### traceEvents

Lista de eventos. No se incluye si `format=gprof`.

* Un evento `"ph":"M"` por cada hilo, con su nombre (`Main Thread` para el hilo principal; en Velneo vServer, `VATP worker N` para cada conexión de cliente y otros hilos de tareas).
* Un evento `"ph":"X"` por cada elemento medido, con:
  * `name`: nombre del elemento.
  * `cat`: categoría: `PROCESS`, `SUBPROC`, `EVENT`, `JS`, `FUNCTION`, `FORMULA`, `DISK`, `SEARCH`, `TCP WAIT` (VATP WAIT) o `TCP CMD` (VATP CMD).
  * `ts` y `dur`: inicio y duración en microsegundos. En modo `aggregate` los inicios no son reales: los hijos se colocan uno tras otro para conservar la jerarquía.
  * `tid`: hilo.
  * `args.calls`: número de llamadas acumuladas (en modo `timeline` siempre es 1).
  * `args.id`: identificador del objeto.
  * `args.topChildren`: solo en modo `aggregate`, los tres elementos hijos con más peso.

## Límites

* Modo `timeline`: hasta `maxEvents` eventos por hilo (por defecto 1.000.000, unos 48 MB de memoria por hilo).
* Se conservan como máximo 1024 hilos finalizados.
* No se miden de forma individual los refrescos de objetos de interfaz ni cada instrucción de un proceso.

## Consideraciones por plataforma

**Linux y macOS:** al ejecutar Velneo vClient desde el gestor de arranque habitual de la plataforma, el guardado no siempre resulta visible; se recomienda ejecutar el cliente directamente desde una *shell* del sistema para comprobar la generación del fichero.

[**Velneo vClient Web**](/38/velneo-vclient-web.md)**:** al no haber línea de comandos, no admite el parámetro `/profiler` ni, por tanto, **Ctrl + F12**. El perfilador solo se puede activar con las funciones JavaScript de VApp. El fichero no se guarda en disco, sino que el navegador lo descarga.
