Bon bah, je viens de faire des tests … Et comme ça je dirais que le problème n’est surement pas les requetes à DuckDB (je crois d’ailleurs qu’on avait déjà fait ce genre de tests directement en dev dans Gladys ^^). Ce doit être simplement le rendu ou plutot la construction des séries … :
- Agrégation par bucket temporel - Requete TimeBucket
SELECT
device_feature_id,
TIME_BUCKET(INTERVAL 1752 MINUTES, created_at) AS created_at,
AVG(value) AS value,
MAX(value) AS max_value,
MIN(value) AS min_value,
SUM(value) AS sum_value,
COUNT(value) AS count_value
FROM t_device_feature_state
WHERE device_feature_id IN (
'eaa982b7-a3c8-4b4d-b2d0-5a5cf5245938',
'e9079170-4654-4fad-b726-23a36c793905',
'c59fca37-54f3-418b-b27c-857e08e2a0fb',
'da79df66-dcff-438e-859c-39b641fd15e9',
'5eba10ac-4c3a-479c-aba7-a1e74a00d914',
'4b5e90f0-a86b-405b-8ca1-953705ef79a3',
'c92f8fa3-d841-4692-bd3a-e5addb760a73',
'b5445f10-7aa9-41bf-8cae-d2f30498652f',
'08e90478-4bb2-4a08-986f-3d6f212c95f1',
'85311f8c-334f-4b7e-8294-2b841c0b8fe8'
)
AND created_at > TIMESTAMP '2024-12-14 10:04:11.478'
GROUP BY
device_feature_id,
created_at
ORDER BY
device_feature_id,
created_at;
- Découpage par quantiles - Requete NTILE(300)
WITH intervals AS (
SELECT
device_feature_id,
created_at,
value,
NTILE(300) OVER (
PARTITION BY device_feature_id
ORDER BY created_at
) AS interval
FROM t_device_feature_state
WHERE device_feature_id IN (
'eaa982b7-a3c8-4b4d-b2d0-5a5cf5245938',
'e9079170-4654-4fad-b726-23a36c793905',
'c59fca37-54f3-418b-b27c-857e08e2a0fb',
'da79df66-dcff-438e-859c-39b641fd15e9',
'5eba10ac-4c3a-479c-aba7-a1e74a00d914',
'4b5e90f0-a86b-405b-8ca1-953705ef79a3',
'c92f8fa3-d841-4692-bd3a-e5addb760a73',
'b5445f10-7aa9-41bf-8cae-d2f30498652f',
'08e90478-4bb2-4a08-986f-3d6f212c95f1',
'85311f8c-334f-4b7e-8294-2b841c0b8fe8'
)
AND created_at > TIMESTAMP '2024-12-14 10:04:11.478'
)
SELECT
device_feature_id,
MIN(created_at) AS created_at,
AVG(value) AS value,
MAX(value) AS max_value,
MIN(value) AS min_value,
SUM(value) AS sum_value,
COUNT(value) AS count_value
FROM intervals
GROUP BY
device_feature_id,
interval
ORDER BY
device_feature_id,
created_at;
J’ai donc refait un test de performance sur le dashboard :
Etude ChatGPT ^^ :
Lecture directe de ton enregistrement Performance
Durée totale
- Total ≈ 13 190 ms (13,2 s)
Répartition (panneau de gauche)
- Affichage (Rendering) : 2 330 ms
- Rendu (Paint / Layout) : 791 ms
- Script (JS) : 563 ms
- Chargement réseau : 27 ms
- Système / non attribué : ~5 200 ms
- Total “utile” visible : ~4 s
- Gros trou “non attribué / idle / attente” : ~9 s
Conclusion immédiate :
ce n’est ni le réseau,
ni DuckDB,
ni le JavaScript pur,
c’est majoritairement du temps d’attente avant que le rendu utile démarre.
Focus sur la partie Réseau (clé pour Gladys)
Dans ton tableau à droite :
- Requête :
aggregated_states (10.5.0.227)
- Taille transférée : 213 ko
- Temps d’exécution : ~260 ms
Ça confirme ce qu’on soupçonnait :
- la requête backend est rapide
- le payload est raisonnable
- < 300 ms, donc pas le problème
On peut désormais dire sans ambiguïté :
Les 10–13 secondes ne viennent pas des requêtes DuckDB.
Où se perdent alors les ~9 secondes ?
D’après le flame chart et la timeline :
Phase “attente / non attribuée” (~9 s)
C’est typiquement :
- attente d’un state React complet
- attente que toutes les séries soient prêtes
- synchronisation avant montage du graphique
- ou logique type :
- “on attend toutes les promesses”
- “on attend que X soit calculé avant de rendre”
Anti-pattern classique sur les dashboards complexes.
Phase “Rendering + Layout” (~3 s)
Là, on est clairement sur :
- beaucoup de points
- beaucoup de séries
- probablement :
- recalcul d’échelles
- recalcul de légendes
- tooltips
- min/max
- animations
C’est cohérent avec un graphe annuel multi-courbes.
Conclusion (que tu peux déjà formuler)
Tu peux déjà dire, preuves à l’appui :
Les mesures Chrome Performance montrent que :
- la requête backend est < 300 ms
- le payload est ~213 ko
- le JS pur < 600 ms
Les ~13 s ressenties sont principalement dues à une phase d’attente + rendu graphique côté front.
L’optimisation doit donc se faire majoritairement sur le pipeline de rendu React / graphe, pas sur DuckDB.
Prochaines pistes concrètes (si tu veux aller plus loin)
Sans même voir le code, les leviers évidents sont :
- rendre le graphe progressivement (séries une par une)
- limiter le nombre de points avant le rendu (hard cap)
- désactiver animations / transitions sur les vues longues
- virtualiser / canvas pur si ce n’est pas déjà le cas