Profiling — introduction
Profile le code lent de ton app, visualise un flame graph dans le dashboard mobile, et détecte automatiquement les régressions de performance entre releases. Modèle “transaction-scoped” — tu choisis quel chemin tu instrumentes plutôt que de payer un sampler en continu.
Pourquoi profiler ?
Section intitulée « Pourquoi profiler ? »Le crash monitoring te dit où ça plante. Le profiling te dit où c’est lent :
- Un écran qui met 3 sec à monter mais qui ne crashe jamais → invisible pour le crash monitor, visible avec le profiler
- Une régression de perf après un refactor → graph cross-release qui flag la fonction coupable
- Un endpoint backend qui consomme 80 % du CPU sous load → flame graph qui pointe la fonction
C’est le pendant performance du crash monitor.
Architecture en 3 lignes
Section intitulée « Architecture en 3 lignes »- Le SDK collecte des samples de stack pendant un intervalle (1 ms par défaut sur Hermes/V8)
- Le SDK POST le blob brut à
/api/profilesà la fin de chaque transaction profilée - Les samples sont agrégés en P50/P95/P99 par fonction × release pour le flame graph + le diff cross-release
Quickstart React Native
Section intitulée « Quickstart React Native »import { Pionne } from '@pionne/react-native';
// Sugar — wrap une transaction entièreawait Pionne.profile('CheckoutFlow', async () => { await fetchCart(); await applyDiscount(); await submitOrder();}, { route: '/checkout' });
// Ou manuel pour plus de contrôlePionne.startProfile('HomeScreenMount', { route: '/home' });// … render path …const profileId = await Pionne.stopProfile();console.log('Profile shipped:', profileId);startProfile renvoie false silencieusement si Hermes n’expose pas le sampler (JSC, certaines vieilles versions). Ton code reste engine-agnostic — pas de runtime check à écrire.
Pionne.profile(name, fn, meta?) est le sucre recommandé : il garantit que stopProfile est appelé même si fn throw, et il retourne ce que fn retourne.
Format JSON côté wire
Section intitulée « Format JSON côté wire »Tu peux poster directement à POST /api/profiles si tu veux profiler un SDK qui n’a pas encore d’implémentation native. Le backend accepte deux formats :
Format produit par Hermes, V8 (--cpu-prof), Chrome DevTools.
{ "name": "CheckoutFlow", "platform": "react_native", "release": "1.4.2", "environment": "production", "route": "/checkout", "duration_ms": 2840, "samples_count": 2840, "sample_interval_us": 1000, "samples": { "traceEvents": [ { "ph": "X", "name": "App.render", "ts": 0, "dur": 1200 }, { "ph": "X", "name": "Cart.fetch", "ts": 1200, "dur": 980 }, { "ph": "X", "name": "Order.submit", "ts": 2180, "dur": 660 } ] }}L’agrégateur ne lit que les events ph: "X" (complete events avec dur explicite). Les paires B/E (begin/end) sont ignorées dans le MVP.
Format produit par Excimer (PHP), stackcollapse.pl, et n’importe quel transcodeur pprof simple.
{ "name": "OrderController::store", "platform": "php", "release": "1.4.2", "environment": "production", "route": "POST /orders", "duration_ms": 480, "samples_count": 48, "sample_interval_us": 10000, "samples": [ { "stack": "main;App\\Http\\Kernel::handle;App\\Http\\Controllers\\OrderController::store", "weight_us": 320000 }, { "stack": "main;App\\Http\\Kernel::handle;App\\Http\\Controllers\\OrderController::store;App\\Services\\PaymentService::charge", "weight_us": 280000 }, { "stack": "main;App\\Http\\Kernel::handle;App\\Http\\Controllers\\OrderController::store;DB::transaction", "weight_us": 95000 } ]}Chaque ligne = une stack (séparée par ;) + son temps inclusif en microsecondes. Plus simple à générer que Chrome Trace si tu pars d’un sampler maison.
Auth : header X-Pionne-Token: pio_live_… (le même que pour /ingest).
Réponse :
{ "ok": true, "profile_id": 42 }Overhead par plateforme
Section intitulée « Overhead par plateforme »| SDK | Profiler natif | Overhead pendant capture |
|---|---|---|
| RN (Hermes) | HermesInternal.enableSamplingProfiler | 1–3 % CPU |
| Web | Performance.profile() (Chrome only) | 2–5 % CPU |
| Node | V8 inspector | 3–8 % CPU |
| PHP (Excimer) | wall-clock sampler | ~1 % wall-clock |
| Flutter | Dart VM Profiler | 2–5 % CPU |
Quand le profiler n’est pas actif → 0 % overhead. C’est le gros avantage du modèle transaction-scoped : tu paies le coût uniquement sur les chemins que tu instrumentes.
Voir aussi
Section intitulée « Voir aussi »- SDK React Native — install + auto-capture
- API Ingest — l’endpoint frère de
/profiles - Bundle ID Pinning — mobile only, ne s’applique pas aux profiles uploadés depuis le backend