> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wrappy.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Performance des scènes

> L'événement `scene_perf` : un rapport par scène montée, sur l'appareil du destinataire, pour trier dans PostHog ce qui charge mal, par scène, appareil et GPU.

## Le principe

Chaque scène montée par `WrappyView` remonte **un** événement `scene_perf`. Il part 5 s après la
première frame, pour que l'ouverture qui s'anime et les textures peintes après l'affichage soient
comptées. Il part plus tôt si la page passe en arrière-plan (`outcome: hidden`, envoyé en
`sendBeacon`), ou au bout de 30 s sans première frame (`outcome: timeout`).

La mesure vit dans `@wrappy/core` (`lib/scene-perf.ts`), sans PostHog. L'hôte l'écoute par
`onScenePerf` et capture l'événement : `apps/open`, sur `/$token` (`host: token`) et `/preview`
(`host: preview`, la démo de la landing quand `embedded` est vrai). Le studio ne l'écoute pas.

## Les jalons

Les instants `t_*_ms` partent du début de la navigation de la page qui monte la scène.

| Jalon | Ce qui vient de finir |
| - | - |
| `t_view_ms` | `WrappyView` est rendu |
| `t_canvas_ms` | Le chunk de la scène est évalué, son canvas monte |
| `t_renderer_ms` | `WebGPURenderer.init()` a rendu son backend |
| `t_assets_ms` | Le Suspense du canvas a résolu : polices, modèles, textures |
| `t_first_frame_ms` | La première frame complète est rendue |

Les durées qui en découlent : `chunk_ms` (vue → canvas), `assets_ms` (canvas → assets),
`view_to_frame_ms` (vue → première frame), et `first_frame_ms`, le travail de la première frame
seule : la compilation des shaders et l'envoi des textures.

## Le main thread et les frames

* `blocking_ms`, `long_tasks` et `longest_task_ms` comptent les tâches longues depuis le début de
  la navigation. La source est `long-animation-frame` sur Chromium 123+, `longtask` sinon
  (`long_tasks_api`). Safari et Firefox n'en observent pas : ces champs valent `null`, pas 0.
* `blocking_after_frame_ms` ne garde que le blocage qui suit la première frame : le travail que la
  scène repousse après son affichage.
* `frames`, `frame_p50_ms`, `frame_p95_ms`, `frame_max_ms` et `slow_frames` (au-delà de 33 ms)
  portent sur le temps CPU des frames rendues après les assets. En rendu à la demande, une scène au
  repos ne rend rien : peu de frames n'est pas un problème.

## Le GPU et l'appareil

* `backend` (`webgpu` ou `webgl`, celui qui rend vraiment), `webgpu_compat`, et `gpu` : le nom de
  l'adaptateur WebGPU ou le renderer WebGL démasqué. `null` quand le navigateur le tait.
* La charge de la première frame : `draw_calls`, `triangles`, `programs`, `textures`,
  `gpu_memory_mb`.
* L'appareil : `mobile`, `device_memory_gb` (plafonné à 8 par Chromium), `cpu_cores`, `dpr`,
  `viewport_width`, `viewport_height`, `effective_type`, `save_data`. Navigateur, OS et modèle
  viennent des propriétés PostHog (`$browser`, `$os`, `$device_type`).

Aucune donnée personnelle : ni token, ni nom, ni payload.

## Lire les données

Le p75 de la première frame par scène et par GPU, sur mobile :

```sql theme={null}
SELECT properties.scene_id, properties.gpu,
  quantile(0.75)(toFloat(properties.view_to_frame_ms)) AS p75_frame,
  quantile(0.75)(toFloat(properties.blocking_ms)) AS p75_blocking,
  count() AS loads
FROM events
WHERE event = 'scene_perf' AND properties.mobile = true AND timestamp > now() - INTERVAL 7 DAY
GROUP BY 1, 2
HAVING loads >= 20
ORDER BY p75_frame DESC
```

Le taux d'abandon, un chargement quitté ou raté avant la première frame :
`countIf(properties.t_first_frame_ms IS NULL) / count()`, par `scene_id` et `device_memory_gb`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.