react-native-skia-webgpu-video 0.0.0-stage → 0.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +303 -2
- package/android/BUILD_VALIDATION.md +62 -0
- package/android/CMakeLists.txt +99 -0
- package/android/build-validation.json +262 -0
- package/android/build.gradle +185 -0
- package/android/cpp/EncoderTargets.cpp +226 -0
- package/android/cpp/EncoderTargets.h +70 -0
- package/android/cpp/JNIHelpers.cpp +15 -0
- package/android/cpp/JNIHelpers.h +20 -0
- package/android/cpp/NativeEventDispatcher.cpp +59 -0
- package/android/cpp/NativeEventDispatcher.h +31 -0
- package/android/cpp/NativeHardwareBuffer.cpp +397 -0
- package/android/cpp/NativeHardwareBuffer.h +34 -0
- package/android/cpp/NativeRgbaBuffer.cpp +45 -0
- package/android/cpp/NativeRgbaBuffer.h +9 -0
- package/android/cpp/ReturnedVideoFrames.h +37 -0
- package/android/cpp/RgbaFrameLease.h +53 -0
- package/android/cpp/VideoCapabilities.cpp +87 -0
- package/android/cpp/VideoCapabilities.h +44 -0
- package/android/cpp/VideoComposition.cpp +170 -0
- package/android/cpp/VideoComposition.h +36 -0
- package/android/cpp/VideoCompositionFramesExtractor.cpp +82 -0
- package/android/cpp/VideoCompositionFramesExtractor.h +48 -0
- package/android/cpp/VideoCompositionFramesExtractorHostObject.cpp +230 -0
- package/android/cpp/VideoCompositionFramesExtractorHostObject.h +42 -0
- package/android/cpp/VideoCompositionFramesExtractorSyncHostObject.cpp +133 -0
- package/android/cpp/VideoCompositionFramesExtractorSyncHostObject.h +46 -0
- package/android/cpp/VideoEncoderHostObject.cpp +318 -0
- package/android/cpp/VideoEncoderHostObject.h +76 -0
- package/android/cpp/VideoFrame.cpp +293 -0
- package/android/cpp/VideoFrame.h +27 -0
- package/android/cpp/VideoPlayer.cpp +96 -0
- package/android/cpp/VideoPlayer.h +52 -0
- package/android/cpp/VideoPlayerHostObject.cpp +225 -0
- package/android/cpp/VideoPlayerHostObject.h +43 -0
- package/android/cpp/cpp-adapter.cpp +316 -0
- package/android/gradle.properties +5 -0
- package/android/instrumentation-inventory.json +178 -0
- package/android/proguard-rules.pro +4 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/azzapp/rnskv/AudioCompositionExporter.java +537 -0
- package/android/src/main/java/com/azzapp/rnskv/AudioCompositionPlayer.java +321 -0
- package/android/src/main/java/com/azzapp/rnskv/BufferLifetime.java +55 -0
- package/android/src/main/java/com/azzapp/rnskv/DecodeRequests.java +100 -0
- package/android/src/main/java/com/azzapp/rnskv/DecoderWindow.java +55 -0
- package/android/src/main/java/com/azzapp/rnskv/EGLResourcesHolder.java +132 -0
- package/android/src/main/java/com/azzapp/rnskv/EGLUtils.java +225 -0
- package/android/src/main/java/com/azzapp/rnskv/FrameSize.java +50 -0
- package/android/src/main/java/com/azzapp/rnskv/GLFrameExtractor.java +510 -0
- package/android/src/main/java/com/azzapp/rnskv/JNIHelpers.java +12 -0
- package/android/src/main/java/com/azzapp/rnskv/NativeEventDispatcher.java +25 -0
- package/android/src/main/java/com/azzapp/rnskv/NativeHardwareBuffer.java +62 -0
- package/android/src/main/java/com/azzapp/rnskv/NativeRgbaBuffer.java +35 -0
- package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoModule.java +45 -0
- package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoPackage.java +43 -0
- package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoSpec.java +9 -0
- package/android/src/main/java/com/azzapp/rnskv/RgbaBufferAllocator.java +83 -0
- package/android/src/main/java/com/azzapp/rnskv/RgbaLayout.java +33 -0
- package/android/src/main/java/com/azzapp/rnskv/SurfaceOutputPolicy.java +13 -0
- package/android/src/main/java/com/azzapp/rnskv/TextureRenderer.java +150 -0
- package/android/src/main/java/com/azzapp/rnskv/TimeHelpers.java +11 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCapabilities.java +354 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoComposition.java +147 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionDecoder.java +772 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractor.java +354 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractorSync.java +241 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionItemDecoder.java +492 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoEncoder.java +639 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoFrame.java +74 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoPlayer.java +361 -0
- package/cpp/RNSVCheckedSizes.h +54 -0
- package/cpp/RNSVEventEmitter.cpp +199 -0
- package/cpp/RNSVEventEmitter.h +31 -0
- package/cpp/RNSVHostObject.cpp +79 -0
- package/cpp/RNSVHostObject.h +67 -0
- package/cpp/RNSVMemoryBudget.cpp +68 -0
- package/cpp/RNSVMemoryBudget.h +100 -0
- package/cpp/RNSVRuntimeLifecycleMonitor.cpp +88 -0
- package/cpp/RNSVRuntimeLifecycleMonitor.h +33 -0
- package/docs/ANDROID_DEVICE_306.md +95 -0
- package/docs/ANDROID_EXPORT_CACHE_306.md +48 -0
- package/docs/ANDROID_MEMORY_RETENTION_306.md +67 -0
- package/docs/BENCHMARKS.md +368 -0
- package/docs/IOS_DEVICE_TESTS.md +115 -0
- package/docs/IOS_SIMULATOR_TESTS.md +74 -0
- package/docs/MIGRATION.md +82 -0
- package/docs/NATIVE_MEMORY_INVESTIGATION_306.md +88 -0
- package/docs/PERFORMANCE_AB_IPHONE_303.md +196 -0
- package/docs/PERFORMANCE_AB_SIMULATOR.md +135 -0
- package/docs/PERFORMANCE_AB_SOAK_SIMULATOR.md +84 -0
- package/docs/PERFORMANCE_IPHONE_306_OPTIMIZATION.md +76 -0
- package/docs/PERFORMANCE_SIMULATOR.md +89 -0
- package/docs/PERFORMANCE_SIMULATOR_INITIAL.md +96 -0
- package/docs/PERFORMANCE_SOAK_IPHONE_303.md +41 -0
- package/docs/UPSTREAM_NOTES.md +188 -0
- package/docs/assets/banner.svg +26 -0
- package/examples/webgpu-overlay.ts +147 -0
- package/ios/AVAssetTrackUtils.h +24 -0
- package/ios/AudioCompositionUtils.h +27 -0
- package/ios/AudioCompositionUtils.mm +113 -0
- package/ios/DecoderWindow.h +52 -0
- package/ios/NativeResourceStats.h +32 -0
- package/ios/RNSVColorSpace.h +50 -0
- package/ios/RNSVJSIUtils.h +46 -0
- package/ios/RNSVScopedPixelBuffer.h +17 -0
- package/ios/RNSVVideoPlayer.h +46 -0
- package/ios/RNSVVideoPlayer.mm +410 -0
- package/ios/ReactNativeSkiaVideo.h +8 -0
- package/ios/ReactNativeSkiaVideo.mm +310 -0
- package/ios/SeekPolicy.h +27 -0
- package/ios/VideoComposition.h +148 -0
- package/ios/VideoCompositionFramesExtractorHostObject.h +105 -0
- package/ios/VideoCompositionFramesExtractorHostObject.mm +686 -0
- package/ios/VideoCompositionFramesExtractorSyncHostObject.h +37 -0
- package/ios/VideoCompositionFramesExtractorSyncHostObject.mm +168 -0
- package/ios/VideoCompositionItemDecoder.h +60 -0
- package/ios/VideoCompositionItemDecoder.mm +480 -0
- package/ios/VideoEncoderHostObject.h +83 -0
- package/ios/VideoEncoderHostObject.mm +706 -0
- package/ios/VideoFrame.h +66 -0
- package/ios/VideoFrame.mm +108 -0
- package/ios/VideoPlayerHostObject.h +52 -0
- package/ios/VideoPlayerHostObject.mm +332 -0
- package/lib/module/NativeReactNativeSkiaVideo.js +5 -0
- package/lib/module/NativeReactNativeSkiaVideo.js.map +1 -0
- package/lib/module/RNSkiaVideoModule.js +20 -0
- package/lib/module/RNSkiaVideoModule.js.map +1 -0
- package/lib/module/canvas.js +18 -0
- package/lib/module/canvas.js.map +1 -0
- package/lib/module/exportCache.js +22 -0
- package/lib/module/exportCache.js.map +1 -0
- package/lib/module/exportFrames.js +338 -0
- package/lib/module/exportFrames.js.map +1 -0
- package/lib/module/exportQueue.js +52 -0
- package/lib/module/exportQueue.js.map +1 -0
- package/lib/module/exportTarget.js +137 -0
- package/lib/module/exportTarget.js.map +1 -0
- package/lib/module/exportVideoComposition.js +492 -0
- package/lib/module/exportVideoComposition.js.map +1 -0
- package/lib/module/frameInterop.js +532 -0
- package/lib/module/frameInterop.js.map +1 -0
- package/lib/module/gpu.js +222 -0
- package/lib/module/gpu.js.map +1 -0
- package/lib/module/gpuDevice.js +54 -0
- package/lib/module/gpuDevice.js.map +1 -0
- package/lib/module/index.js +36 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/memory.js +38 -0
- package/lib/module/memory.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/previewLifecycle.js +52 -0
- package/lib/module/previewLifecycle.js.map +1 -0
- package/lib/module/runtimeYield.js +10 -0
- package/lib/module/runtimeYield.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/useEventListener.js +18 -0
- package/lib/module/utils/useEventListener.js.map +1 -0
- package/lib/module/videoCompositionPlayer.js +348 -0
- package/lib/module/videoCompositionPlayer.js.map +1 -0
- package/lib/module/videoFrameImage.js +185 -0
- package/lib/module/videoFrameImage.js.map +1 -0
- package/lib/module/videoPlayer.js +172 -0
- package/lib/module/videoPlayer.js.map +1 -0
- package/lib/module/yuvBlit.js +299 -0
- package/lib/module/yuvBlit.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts +7 -0
- package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts.map +1 -0
- package/lib/typescript/src/RNSkiaVideoModule.d.ts +4 -0
- package/lib/typescript/src/RNSkiaVideoModule.d.ts.map +1 -0
- package/lib/typescript/src/canvas.d.ts +4 -0
- package/lib/typescript/src/canvas.d.ts.map +1 -0
- package/lib/typescript/src/exportCache.d.ts +6 -0
- package/lib/typescript/src/exportCache.d.ts.map +1 -0
- package/lib/typescript/src/exportFrames.d.ts +57 -0
- package/lib/typescript/src/exportFrames.d.ts.map +1 -0
- package/lib/typescript/src/exportQueue.d.ts +5 -0
- package/lib/typescript/src/exportQueue.d.ts.map +1 -0
- package/lib/typescript/src/exportTarget.d.ts +28 -0
- package/lib/typescript/src/exportTarget.d.ts.map +1 -0
- package/lib/typescript/src/exportVideoComposition.d.ts +68 -0
- package/lib/typescript/src/exportVideoComposition.d.ts.map +1 -0
- package/lib/typescript/src/frameInterop.d.ts +17 -0
- package/lib/typescript/src/frameInterop.d.ts.map +1 -0
- package/lib/typescript/src/gpu.d.ts +39 -0
- package/lib/typescript/src/gpu.d.ts.map +1 -0
- package/lib/typescript/src/gpuDevice.d.ts +11 -0
- package/lib/typescript/src/gpuDevice.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +21 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/memory.d.ts +25 -0
- package/lib/typescript/src/memory.d.ts.map +1 -0
- package/lib/typescript/src/previewLifecycle.d.ts +22 -0
- package/lib/typescript/src/previewLifecycle.d.ts.map +1 -0
- package/lib/typescript/src/runtimeYield.d.ts +4 -0
- package/lib/typescript/src/runtimeYield.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +631 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/useEventListener.d.ts +5 -0
- package/lib/typescript/src/utils/useEventListener.d.ts.map +1 -0
- package/lib/typescript/src/videoCompositionPlayer.d.ts +85 -0
- package/lib/typescript/src/videoCompositionPlayer.d.ts.map +1 -0
- package/lib/typescript/src/videoFrameImage.d.ts +60 -0
- package/lib/typescript/src/videoFrameImage.d.ts.map +1 -0
- package/lib/typescript/src/videoPlayer.d.ts +99 -0
- package/lib/typescript/src/videoPlayer.d.ts.map +1 -0
- package/lib/typescript/src/yuvBlit.d.ts +50 -0
- package/lib/typescript/src/yuvBlit.d.ts.map +1 -0
- package/package.json +154 -4
- package/patches/react-native-skia+3.7.0.patch +502 -0
- package/react-native-skia-webgpu-video.podspec +35 -0
- package/scripts/apply-skia-canvas-patch.mjs +48 -0
- package/scripts/skia-canvas-patch.json +291 -0
- package/src/NativeReactNativeSkiaVideo.ts +8 -0
- package/src/RNSkiaVideoModule.ts +27 -0
- package/src/canvas.ts +22 -0
- package/src/exportCache.ts +27 -0
- package/src/exportFrames.ts +421 -0
- package/src/exportQueue.ts +65 -0
- package/src/exportTarget.ts +179 -0
- package/src/exportVideoComposition.ts +718 -0
- package/src/frameInterop.ts +684 -0
- package/src/gpu.ts +290 -0
- package/src/gpuDevice.ts +80 -0
- package/src/index.tsx +45 -0
- package/src/memory.ts +48 -0
- package/src/previewLifecycle.ts +60 -0
- package/src/runtimeYield.ts +6 -0
- package/src/types.ts +661 -0
- package/src/utils/useEventListener.ts +22 -0
- package/src/videoCompositionPlayer.ts +520 -0
- package/src/videoFrameImage.ts +205 -0
- package/src/videoPlayer.ts +318 -0
- package/src/yuvBlit.ts +331 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Exécuter les tests sur l'iPhone
|
|
2
|
+
|
|
3
|
+
Mise à jour du **19 octobre 2026** (Skia 3.7.0 / WebGPU 0.17.0) : quatre runs Release sur iPhone 15 Pro hors chargeur, en alternant 3.7.0 et 3.6.1, avec trois répétitions par cas. L'export iOS ne change pas : profil par image et octets produits identiques. Médianes 3.7.0 : HEVC 1080p 731 ms, H.264 640×360 168–171 ms, 8×4K réduits 2,73–2,79 s, contre 734 ms, 173–211 ms et 2,74–2,78 s en 3.6.1. Une première série, faite sur chargeur sans fil, a été écartée : le téléphone y passe en état thermique *fair* et ralentit de 15 à 80 %. Voir la [vérification](../migration/skia-3.7.0/verification.md#appareil-ios--iphone-15-pro).
|
|
4
|
+
|
|
5
|
+
Mise à jour du **16 octobre 2026** (Skia 3.6.1 / WebGPU 0.16.0) : quatre runs Release sur iPhone 15 Pro, en alternant 3.4.4 et 3.6.1, avec trois répétitions par cas. L'export iOS ne change pas : le profil par image est identique dans les quatre séries, tout comme les octets produits. Les médianes sont HEVC 1080p 728–790 ms, H.264 640×360 168–169 ms et 8×4K réduits 2,68–2,73 s, contre 731–734 ms, 174–223 ms et 2,72–2,79 s en 3.4.4. Voir la [vérification](../migration/skia-3.6.1/verification.md#appareil-ios--iphone-15-pro).
|
|
6
|
+
|
|
7
|
+
Mise à jour du **15 octobre 2026** (Skia 3.4.4 / WebGPU 0.14.2) : trois runs Release sur iPhone 15 Pro, dans l'ordre nouvelle version, 3.0.6, nouvelle version, avec trois répétitions par cas.
|
|
8
|
+
- **Résultats :** HEVC 1080p **956 → 735/738 ms**, H.264 640×360 **235 → 210/175 ms**, 8×4K réduits **2,95 → 2,73/2,85 s**, avec des tailles de sortie identiques.
|
|
9
|
+
- **Profil :** il est enregistré par cas (`exportProfile`).
|
|
10
|
+
- **Cas `4k-x3-simultaneous` :** il s'arrête sur le budget mémoire pendant la lecture, dans les deux versions.
|
|
11
|
+
- **Détails :** [vérification](../migration/skia-3.4.4/verification.md#appareil-ios--iphone-15-pro).
|
|
12
|
+
|
|
13
|
+
Ces runs utilisent `scripts/test-ios-device-ab-run.mjs` avec une app signée par l'équipe personnelle (`--team`). L'iPhone doit approuver ce développeur une fois (Réglages → Général → VPN et gestion de l'appareil), sinon le lancement est refusé.
|
|
14
|
+
|
|
15
|
+
Mise à jour du **8 octobre 2026** : la [correction de la boucle d’export](NATIVE_MEMORY_INVESTIGATION_306.md) a passé deux montages comparatifs puis **6/6 montages complets consécutifs** sur iPhone 15 Pro en Release, avec conditions nominal/normal/active. Après deux montages et 60 s au repos, l’empreinte physique passe de **425,99 à 257,70 Mio** ; après six montages, elle est de **277,74 Mio** au repos. Ces tests du scénario ne constituent pas une nouvelle exécution des 50 XCTest historiques ci-dessous.
|
|
16
|
+
|
|
17
|
+
L'application de test est isolée dans [`example`](../example). Le workspace est `example/ios/ReactNativeSkiaWebGPUVideoExample.xcworkspace`, le schéma **ReactNativeSkiaWebGPUVideoExample** et la destination est votre iPhone connecté. Les bundle IDs `com.seb.skiawebgpuvideo.test` et `com.seb.skiawebgpuvideo.test.tests` permettent d'installer l'exemple séparément de l'application existante.
|
|
18
|
+
|
|
19
|
+
Le premier build **Skia 3.0.6 / WebGPU 0.12.1** a passé **50/50 XCTest natifs**, aucun échec ni skip, sur **iPhone 15 Pro / iOS 27.0.1**, terminé le **7 octobre à 08:23:15.311 UTC** : [preuve native 3.0.6](../benchmark/ios-native-device-306-verification.json). Ce run valide les cas natifs du build initial. Après les refus initiaux de lancement sur iPhone verrouillé, le smoke optimisé a passé **5/5 cas physiques**. La [comparaison initial/optimisé 3.0.6](PERFORMANCE_IPHONE_306_OPTIMIZATION.md) a terminé **96/96 exécutions et 24 fichiers / 1440 frames sondés** ; tous les relevés sont fair/normal/active, donc le protocole nominal n’est pas satisfait. La baisse descriptive d’empreinte physique ne s’accompagne pas d’un gain global de vitesse. Le build optimisé est laissé installé après cette passe. Le transport optimisé a passé **14/14 cas ciblés sur simulateur Release**, une répétition chacun, avec **27 exports / 1320 frames sondés** et compteurs suivis à zéro après fermeture : [preuve fonctionnelle distincte](../benchmark/ios-simulator-306-functional-verification.json). Les pixels réels et l’immutabilité visuelle held restent non validés ; ce run ne remplace pas les essais physiques ou une comparaison de performance. Sur l’hôte, le premier run a passé 154 tests Jest / 8 suites ; le transport optimisé a ensuite passé **157 Jest**, les **4 tests du patch**, Bob et publint strict. La [preuve hôte de ce checkpoint](../benchmark/host-verification.json), renouvelée à **08:57:51 UTC**, conserve **189 assertions suivies** après les dernières modifications (157 Jest, 20 C++ historiques, 12 JVM historiques).
|
|
20
|
+
|
|
21
|
+
Les essais physiques **Skia 3.0.3** ont **repris le 7 octobre 2026**. La suite native Release a passé **50/50 XCTest, aucun échec ni skip**, sur **iPhone 15 Pro / iOS 27.0.1**, terminée à **07:23:57 UTC**. [ios-native-device-verification.json](../benchmark/ios-native-device-verification.json) conserve les 50 noms passés, le SDK `iphoneos27.0` et les empreintes des sources vérifiées. Cette preuve native ne constitue pas une mesure de performance ni un A/B.
|
|
22
|
+
|
|
23
|
+
Le smoke du candidat a réussi **5/5 scénarios sur une répétition** ; deux scénarios `direct` de la référence ont également réussi. Ces premiers runs sont fonctionnels : les relevés d'un cas avant activation de l'application restent exclus du timing A/B. Après ajout de la garde commune de premier plan, le [comparatif physique court 3.0.3](PERFORMANCE_AB_IPHONE_303.md) couvre huit scénarios en ABBA : **48/48 réussites candidat, 47/48 référence**. Le premier passage de la référence est principalement fair et conserve un échec HEVC ; la paire BA est entièrement nominale. Ces résultats ciblés ne qualifient pas les 65 workloads du catalogue.
|
|
24
|
+
|
|
25
|
+
Le [diagnostic physique de 300 exports](PERFORMANCE_SOAK_IPHONE_303.md) a passé **3/3 blocs et sondé les 300 fichiers**, avec croissance de la mémoire du processus. Le collecteur de repos a ensuite dépassé son délai à **08:11:30 UTC**, sans fichier de relevés, puis le runner a arrêté son application. Le statut global de l'expérience conserve cet échec de collecte, distinct des exports réussis. La référence a subi un SIGTRAP natif sans JSON comparable. Les tests 3.0.3 sont désormais arrêtés à la demande utilisateur ; la migration **Skia 3.0.6 / WebGPU 0.12.1** a passé sa première suite native iPhone, décrite séparément ci-dessus, avec validation fonctionnelle ciblée du transport optimisé sur simulateur, avec comparaison physique initial/optimisé désormais mesurée séparément ; les performances nominales et un palier physique durable restent à qualifier.
|
|
26
|
+
|
|
27
|
+
Les applications mesurées utilisent RN 0.86.2 et React 19.2.3. Le candidat de ces rapports utilise Skia 3.0.3 / Dawn / WebGPU 0.11.0, Reanimated 4.5.3 et Worklets 0.11.3. Le manifeste a ensuite migré vers Skia 3.0.6 / WebGPU 0.12.1, puis vers Skia 3.4.4 / WebGPU 0.14.2 le 14 octobre. Son premier build a passé 50 XCTest ; une nouvelle compilation ne reproduit pas les binaires 3.0.3 archivés et doit qualifier les optimisations intervenues depuis. Les versions de Skia et des runtimes propres à la référence doivent rester consignées ; elles font partie de la différence étudiée. La [compilation initiale sans signature](../benchmark/ios-build-verification.json) et les [résultats simulateur](IOS_SIMULATOR_TESTS.md) restent des preuves distinctes.
|
|
28
|
+
|
|
29
|
+
## Signature et choix de la cible
|
|
30
|
+
|
|
31
|
+
1. Ouvrir le fichier `.xcworkspace` indiqué ci-dessus dans Xcode.
|
|
32
|
+
2. Dans **Xcode > Settings > Accounts**, connecter le compte Apple de développement si aucun compte n'est présent. Effectuer cette connexion directement dans Xcode ; aucun mot de passe ne doit être partagé dans le chat ou enregistré dans le dépôt.
|
|
33
|
+
3. Dans **Signing & Capabilities**, choisir l'équipe de développement et activer **Automatically manage signing** pour l'application **et** `ReactNativeSkiaWebGPUVideoExampleTests`. Conserver leurs bundle IDs distincts. Un certificat présent sur le Mac ne suffit pas si le profil de ces cibles manque.
|
|
34
|
+
4. Sélectionner le schéma **ReactNativeSkiaWebGPUVideoExample** et la destination correspondant à votre iPhone. Garder le téléphone connecté et déverrouillé pendant l'installation.
|
|
35
|
+
|
|
36
|
+
Le projet public ne contient aucune équipe de signature. Utiliser `--team APPLE_TEAM_ID` pour signer sans enregistrer cet identifiant dans le projet ; si vous configurez l’équipe directement dans Xcode, conserver cette modification localement. Si l'appareil refuse un certificat, l'approuver dans **Settings > General > VPN & Device Management**. La déclaration UIScene et le linkage XCTest ont été corrigés après l'échec initial de lancement.
|
|
37
|
+
|
|
38
|
+
Le script depuis la racine du dépôt reprend la compilation et l'exécution en Release :
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
node scripts/test-ios-device.mjs --device IPHONE_UDID --team APPLE_TEAM_ID --native
|
|
42
|
+
node scripts/test-ios-device.mjs --device IPHONE_UDID --team APPLE_TEAM_ID --launch --profile smoke
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Remplacer `IPHONE_UDID` par l'identifiant dans Xcode. Le script utilise aussi `example/device.local.json` lorsqu'il existe. L'option `--team APPLE_TEAM_ID` permet de choisir explicitement une équipe ; en son absence, il conserve la configuration Xcode. `--launch` seul ouvre le menu, `--profile full` et `--profile soak` démarrent les autres profils. `--build-only` compile et signe sans exécuter ; `--unsigned` ne vérifie que la compilation et ne peut pas installer l'application. Le dossier des logs et du `.xcresult` est affiché par le script.
|
|
46
|
+
|
|
47
|
+
## Les 50 cas natifs
|
|
48
|
+
|
|
49
|
+
Le schéma partagé utilise désormais **Release** pour l'action Test. Lancer **Product > Test** ou **Cmd+U**. Si le schéma a été modifié localement, vérifier sa configuration dans **Product > Scheme > Edit Scheme**.
|
|
50
|
+
|
|
51
|
+
La cible utilise [`ios/tests/LegacyParityTests.mm`](../ios/tests/LegacyParityTests.mm) : décodeurs, fenêtre de frames, preview, export, orientation, timestamps, fermeture et slow motion. Le test slow motion construit sa propre présentation par edit list ; la fixture commune au benchmark a également été produite comme fichier autonome. Conserver le rapport `.xcresult` et les échecs éventuels. Une compilation des 50 méthodes ne doit jamais être enregistrée comme 50 tests réussis.
|
|
52
|
+
|
|
53
|
+
Les deux runs natifs physiques 3.0.3 puis 3.0.6 ont été vérifiés contre **les 50 méthodes concrètes des sources**. La preuve initiale 3.0.6 contrôle 54 entrées iOS/C++/pods/manifeste/headers patchés et leurs dates avant l’invocation ; elle exclut les sources Android/JavaScript et ne fabrique pas de fingerprint global pré-build. L’empreinte limitée `e8fafd5b…` et les hashes du binaire/bundle XCTest archivé permettent de distinguer ce premier build des optimisations ultérieures. Le run **3.0.3** avait été vérifié avec une seule destination iOS physique et un statut Passed pour chaque nom. Les 100 fichiers de production, dépendances, projet et fixture contrôlés précèdent le début de la compilation et sont restés inchangés pendant l'extraction. L'empreinte de production est `486b12a…`. Le test JPEG impair utilise la vraie fixture 1279×719. La modification ultérieure de la garde de premier plan du harness concerne les mesures JavaScript ; elle ne transforme pas cette suite native en qualification du harness.
|
|
54
|
+
|
|
55
|
+
La tentative du **6 octobre**, avant correctifs, reste conservée avec **45 réussites et 5 échecs**, sans skip, dans [ios-native-device-attempt.json](../benchmark/ios-native-device-attempt.json). Elle portait sur les petites seeks, le scrub, le seek en pause, les dimensions impaires et la slow motion. Le premier smoke de ce jour avait échoué au montage (`Cannot read property 'current' of undefined`) puis bloqué quatre cas, avec des ressources suivies encore présentes. Ces résultats historiques et leurs JSON bruts ne sont pas remplacés par le succès actuel.
|
|
56
|
+
|
|
57
|
+
## Lecture, export et mémoire en Release
|
|
58
|
+
|
|
59
|
+
L'action **Run** du schéma utilise aussi **Release**. Reconstruire l'application après les dernières modifications JavaScript/natives, puis lancer **Product > Run** ou **Cmd+R**. Le bundle Release est intégré à l'application ; il permet de poursuivre les tests sans dépendre d'une connexion à Metro. Le bandeau « Build Debug » doit être absent dans l'écran de test.
|
|
60
|
+
|
|
61
|
+
L'écran propose :
|
|
62
|
+
|
|
63
|
+
- **Test rapide** : vérifier d'abord la lecture, l'export et la fermeture sur le téléphone.
|
|
64
|
+
- **Tous les scénarios** : parcourir le catalogue actuel de **65 workloads**, version **2026-10-07.1**.
|
|
65
|
+
- **Test prolongé** : augmenter les seeks et les cycles de création/fermeture pour suivre la croissance mémoire après warmup.
|
|
66
|
+
|
|
67
|
+
Chaque profil utilise par défaut **trois répétitions**, le manifest des fichiers et un budget explicite de **512 Mio de réservations internes**. Une répétition sert d'abord à vérifier le fonctionnement. Cette configuration de benchmark diffère de la valeur par défaut de 256 Mio de la bibliothèque ; reprendre la même limite et les mêmes options dans le build de référence.
|
|
68
|
+
|
|
69
|
+
Quatorze médias sont présents dans `example/fixtures` et sondés par AVFoundation : H.264/HEVC, 4K, 60 fps, HLG 10 bits, rotations, audio et slow motion avec edit list. La preuve d'inclusion du simulateur ne remplace pas celle des builds physiques : le runner A/B vérifie le manifest et les hashes des médias embarqués dans chacun des `.app` signés. Les adaptateurs LUT/compute/Three.js/Core ML ne sont pas branchés dans cet écran : leurs cas restent des **non exécutés** explicites. La présence d'un média HLG ne qualifie pas sa précision colorimétrique. Les preuves de génération et d'inclusion initiale sont dans [fixture-generation-status.json](../benchmark/fixture-generation-status.json) et [fixture-bundle-verification.json](../benchmark/fixture-bundle-verification.json).
|
|
70
|
+
|
|
71
|
+
Depuis la version de workload **2026-10-06.3**, la preview demande **720×720 pixels physiques**, soit environ 240×240 points sur cet iPhone à 3x. Le JSON conserve PixelRatio, les dimensions logiques et les dimensions réellement dessinées. Chaque répétition monte puis démonte un enfant avec son Canvas et son hook ; la fermeture attend l'accusé de traitement de la queue UI. Une ancienne mesure à 720 points / 2160 pixels ne se compare pas à cette version.
|
|
72
|
+
|
|
73
|
+
Le module natif de l'exemple lit séparément le **RSS du processus** avec `mach task_info resident_size` et l'**empreinte physique** avec `task_vm_info phys_footprint`, les conditions thermiques/alimentation via `NSProcessInfo`, et décode les fichiers exportés pour contrôler leurs métadonnées, le nombre de frames et les timestamps. Le harness relève ces conditions et l'état de premier plan avec chaque point mémoire. Ces deux métriques concernent tout le processus et ne s'additionnent pas. La mémoire du heap natif et la mémoire GPU totale restent indisponibles sans collecteur supplémentaire. Une progression réussie ou un compteur interne revenu à zéro ne remplace pas ces mesures physiques.
|
|
74
|
+
|
|
75
|
+
Les trois workloads `steady-playback-*` mesurent la lecture sans seeks préalables ; chacun possède une variante `-direct` avec les mêmes temps de composition. Les anciens `single-*` gardent les seeks et tests de cycle de vie. Comparer les mêmes IDs dans les deux builds. Le mode demandé `direct` reste distinct du transport réel annoncé par le backend : le candidat conserve ses copies de référence, même lorsque ce mode est demandé.
|
|
76
|
+
|
|
77
|
+
## Récupérer les résultats et comparer
|
|
78
|
+
|
|
79
|
+
Chaque profil terminé écrit un fichier `candidate-<timestamp>.json` dans **Documents/benchmark-results**. Le chemin apparaît aussi dans la console de l'application. Le dossier sert également aux exports temporaires ; le harness les supprime après validation.
|
|
80
|
+
|
|
81
|
+
Dans **Xcode > Window > Devices and Simulators**, sélectionner votre iPhone, puis l'application installée. Utiliser **Download Container** pour conserver son conteneur. Les fichiers JSON se trouvent dans `AppData/Documents/benchmark-results` du `.xcappdata` téléchargé. Garder les résultats bruts et le rapport XCTest avant de nettoyer ou réinstaller l'application.
|
|
82
|
+
|
|
83
|
+
Pour préparer les deux builds séparés, depuis la racine :
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
node scripts/test-ios-device.mjs --device IPHONE_UDID --team APPLE_TEAM_ID --build-only
|
|
87
|
+
node scripts/test-ios-baseline-device.mjs --device IPHONE_UDID --team APPLE_TEAM_ID
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
La référence isolée est dans `example-baseline`, avec le schéma **ReactNativeSkiaVideoBaseline** et le bundle `com.seb.skiavideo.baseline.test`. Le script de référence exige que `example-baseline/device.local.json` corresponde à l'iPhone demandé ; garder cette identité et `example/device.local.json` dans les fichiers locaux ignorés. `--team APPLE_TEAM_ID` choisit l'équipe de signature. `--install` installe la référence sans lancer de mesures. Les sources du dépôt historique restent inchangées. Conserver les chemins des deux `.app` **Release-iphoneos** imprimés par les builds.
|
|
91
|
+
|
|
92
|
+
Le runner physique utilise ces produits déjà compilés. Exemple de sélection lecture/export en `direct`, à lancer avec des labels uniques :
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
node scripts/test-ios-device-ab-run.mjs --device IPHONE_UDID --backend baseline --label iphone-a1-baseline --app /path/Release-iphoneos/ReactNativeSkiaVideoBaseline.app --profile full --case steady-playback-h264-1080p30-audio-direct --case encode-h264-direct --repetitions 3 --idle-seconds 180 --poll-seconds 30
|
|
96
|
+
node scripts/test-ios-device-ab-run.mjs --device IPHONE_UDID --backend candidate --label iphone-b1-candidate --app /path/Release-iphoneos/ReactNativeSkiaWebGPUVideoExample.app --profile full --case steady-playback-h264-1080p30-audio-direct --case encode-h264-direct --repetitions 3 --idle-seconds 180 --poll-seconds 30
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Répéter ensuite la référence avec un nouveau label `iphone-a2-baseline` pour vérifier la dérive avant/après le candidat. Remplacer les chemins et l'UDID génériques par ceux des builds signés. Répéter `--case ID` pour les autres cas 4K/HEVC ; ne pas modifier les IDs, paramètres, fixtures ou instrumentation entre les deux versions. `--profile soak --case repeated-mixed-size-exports --repetitions 3` produit un diagnostic distinct de 300 exports. Un profil long ne se fusionne pas avec les mesures de lecture.
|
|
100
|
+
|
|
101
|
+
Le runner attend jusqu’à **120 secondes** par défaut si iOS refuse explicitement le lancement avec `BSErrorCodeDescription = Locked`. `--unlock-wait-seconds 0` désactive cette attente ; une valeur jusqu’à 600 secondes est autorisée. Déverrouiller le téléphone pendant cette attente. Seul ce refus de verrouillage provoque un retry du lancement ; les erreurs réseau, de signature ou les crashs ne sont pas assimilés à un verrouillage. Cette attente avant lancement ne change ni la fenêtre mesurée ni le collecteur à 100 ms. Les dix tests ciblés du runner ont passé sur l’hôte.
|
|
102
|
+
|
|
103
|
+
`--idle-seconds` demande des relevés natifs dans l'application toutes les 30 secondes après le run, jusqu'à 600 secondes ; la valeur doit être un multiple de 30. `--poll-seconds` règle seulement la récupération des fichiers, entre 15 et 60 secondes. Un PID retourné par l'iPhone n'est jamais utilisé avec `ps` sur le Mac. Le runner installe et vérifie les hashes avant la mesure, démarre un processus neuf et ne termine que les deux applications de test identifiées. Une coupure de lecture du device conserve le run et provoque une nouvelle tentative ; l'application Release contient son bundle et ne dépend pas de Metro.
|
|
104
|
+
|
|
105
|
+
Chaque label conserve trois fichiers locaux distincts : `LABEL.local.json` (mesures originales), `LABEL-execution.local.json` (identité, hashes, commandes et interruptions), puis `LABEL-idle.local.json` si le repos a été demandé. Un label déjà présent est refusé pour préserver les résultats précédents. Le runner contrôle l'identité de l'iPhone, le processus, le run, le catalogue exact, le mode Release et le collecteur commun de 100 ms ; récupérer un JSON ne signifie pas que tous ses cas ont réussi.
|
|
106
|
+
|
|
107
|
+
Comparer ensuite les JSON correspondant aux mêmes cas :
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
node scripts/benchmark-compare.mjs baseline.json candidate.json comparison.json
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Le candidat seul ne donne aucune conclusion A/B. Un skip, des métriques absentes, moins de trois répétitions, des fixtures différentes ou des conditions qui changent rendent la qualification incomplète. Les callbacks/s ne sont pas des FPS vidéo décodées, le temps mural du callback ne mesure pas le temps GPU, et le RSS représente tout le processus. [BENCHMARKS.md](BENCHMARKS.md) décrit les seuils, les collecteurs et l'interprétation ; le [guide de migration](MIGRATION.md) décrit les limites actuelles.
|
|
114
|
+
|
|
115
|
+
Les rapports bruts du smoke restent dans `benchmark/results/iphone-smoke-candidate-20261007.local.json` et `iphone-direct-smoke-baseline-20261007.local.json`. Les extractions natives exactes sont conservées séparément dans `ios-native-device-xcresult-20261007.local.json` (3.0.3) et `ios-native-device-306-xcresult-20261007.local.json` (3.0.6). Les rapports [courts](PERFORMANCE_AB_IPHONE_303.md) et [prolongés](PERFORMANCE_SOAK_IPHONE_303.md) identifient leurs propres sources et hashes ; aucun résultat 3.0.3 n'est renommé en test 3.0.6. Ces fichiers locaux portent des identités privées et restent ignorés par Git et exclus du paquet. Le guide et les preuves publiques utilisent uniquement des champs anonymisés.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Vérifier le fonctionnement sur le simulateur iOS
|
|
2
|
+
|
|
3
|
+
**19 octobre 2026 (Skia 3.7.0 / WebGPU 0.17.0)** : aucun run simulateur ; les mesures sont sur appareil ([vérification](../migration/skia-3.7.0/verification.md)).
|
|
4
|
+
|
|
5
|
+
**16 octobre 2026 (Skia 3.6.1 / WebGPU 0.16.0)** : 50/50 XCTests natifs en Release sur l'arbre migré. Aucun run de scénarios ni de mesure sur simulateur pour cette version ; les mesures sont sur appareil ([vérification](../migration/skia-3.6.1/verification.md)).
|
|
6
|
+
|
|
7
|
+
**14 octobre 2026 (Skia 3.4.4 / WebGPU 0.14.2)**, sur iPhone 17e, iOS 26.4, en Release :
|
|
8
|
+
- **50/50 XCTest natifs** et **5/5 smoke**.
|
|
9
|
+
- **Attribution A/B des exports :** la référence 3.0.6, la montée de version seule, la fermeture immédiate des imports, puis l'import en place.
|
|
10
|
+
- **Résultat :** aucune différence de vitesse mesurable sur simulateur, qui décode en logiciel, mais −30 % de mémoire suivie pendant l'export avec l'import en place.
|
|
11
|
+
- **Détails :** [vérification](../migration/skia-3.4.4/verification.md) et [JSON](../benchmark/ios-simulator-344-export-ab.json). Les runs iPhone ont repris depuis : voir le [guide iPhone](IOS_DEVICE_TESTS.md).
|
|
12
|
+
|
|
13
|
+
Le simulateur sert à vérifier la lecture, l'export et la fermeture. La cible choisie est **iPhone 18 Pro, iOS 27** ; utiliser son identifiant fourni par Xcode ou `xcrun simctl list devices available`.
|
|
14
|
+
|
|
15
|
+
Le script de la racine utilise le même workspace et schéma que l'exemple iPhone, en **Release**, avec un bundle JavaScript embarqué. Il compile et installe uniquement sur le simulateur, sans signature de développement ni serveur Metro :
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
node scripts/test-ios-simulator.mjs --simulator SIMULATOR_UDID --launch --profile smoke
|
|
19
|
+
node scripts/test-ios-simulator.mjs --simulator SIMULATOR_UDID --launch --profile smoke --case single-h264-638x358.mp4 --repetitions 1
|
|
20
|
+
node scripts/test-ios-simulator.mjs --simulator SIMULATOR_UDID --native
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`--native` exécute la cible contenant les 50 XCTest. `--case ID` isole un scénario et s'utilise avec `--profile smoke`, `full` ou `soak` ; répéter l'option pour sélectionner plusieurs cas. `--repetitions 1` permet d'abord de vérifier son fonctionnement ; la valeur par défaut est trois pour les mesures, mais une répétition ne qualifie pas une comparaison statistique. `--profile full` parcourt le catalogue complet ; `--profile soak` augmente les cycles. `--build-only` compile sans lancer. Le script affiche le dossier des logs et le rapport `.xcresult` du run natif.
|
|
24
|
+
|
|
25
|
+
Pour reproduire les cinq cas de performance sur trois répétitions :
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
node scripts/test-ios-simulator.mjs --simulator SIMULATOR_UDID --launch --profile full --repetitions 3 --case single-h264-1080p30-audio.mp4 --case single-h264-4k30.mp4 --case single-hevc-4k30.mp4 --case encode-h264-copy --case repeated-mixed-size-exports
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Pour un diagnostic distinct de 300 exports, le profil soak applique 100 cycles par répétition à ce seul cas :
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
node scripts/test-ios-simulator.mjs --simulator SIMULATOR_UDID --launch --profile soak --case repeated-mixed-size-exports --repetitions 3
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Conserver les trois sorties séparées : rapport XCTest, JSON des cinq cas mesurés et JSON du diagnostic long. Ne pas les fusionner en un succès du catalogue complet.
|
|
38
|
+
|
|
39
|
+
Le scénario **`single-h264-638x358.mp4` a d'abord réussi en Release**, sur une répétition : 240 callbacks de dessin, aucune frame attendue manquante, cinq seeks, boucle et hold. Le rapport est conservé dans `benchmark/results/simulator-h264.local.json` et indique `executionTarget: simulator`.
|
|
40
|
+
|
|
41
|
+
Le **profil smoke a ensuite réussi ses cinq scénarios**, sur une répétition : montage de huit clips 4K avec décodage borné à 1280, lecture H.264 simple, export H.264, annulation avant export et reprise après seek au-delà de la fin. Les réservations, décodeurs et buffers encodeur suivis reviennent à zéro après chaque cas. Les deux fichiers exportés ont été sondés : 360 frames en 1080×1080 et 60 frames en 640×360, H.264/30 fps avec timestamps exacts. Le rapport brut est conservé dans `benchmark/results/simulator-smoke.local.json`.
|
|
42
|
+
|
|
43
|
+
La confirmation native **actuelle a passé 50/50 XCTest, aucun échec ni skip**, terminée à **16:36:31 UTC**, après les correctifs d'horloge/replay et activation des scopes autorelease synchrones sur le thread Worklets. [ios-simulator-verification.json](../benchmark/ios-simulator-verification.json) conserve les 50 noms passés et les empreintes actuelles `486b12a…`. Le test eager vérifie l'horloge stable après complete, la reprise avec des frames du début et les `play()` répétés idempotents. Le test de la vraie fixture JPEG 1279×719 vérifie ses 30 indices, pixels et dimensions aux temps demandés ; les PTS bruts du fichier ont été vérifiés séparément sur macOS.
|
|
44
|
+
|
|
45
|
+
Le premier catalogue complet de **59 workloads sur une répétition**, version `.3`, achevé à **15:40:56 UTC**, a produit **50 réussites, 2 timeouts, 3 limites de budget et 4 extensions indisponibles**. Le budget de 512 Mio a refusé le montage eager de tous les médias, huit clips 4K eager et trois clips 4K simultanés. Les extensions LUT/compute/Three.js/Core ML ne sont pas branchées. Les 55 cas actifs rendent à zéro les octets, réservations, codecs et buffers en vol suivis, sans erreur de fermeture ni état signalé dangereux. `benchmark/results/simulator-full-first.local.json` conserve ce résultat du build précédent, d'empreinte `4a087400…` ; il ne s'agit pas d'un full sans échec.
|
|
46
|
+
|
|
47
|
+
Les deux timeouts seek/scrub venaient du prédicat du harness, qui attendait une horloge fixe pendant la lecture. La version `.4` vérifie une horloge qui avance depuis le seek, un nouveau rendu, les items visibles et le changement d'identité native disponible. Après correction autorelease, **sept cas ciblés ont passé** entre **16:37:45 et 16:38:43 UTC** : les cinq du smoke et les deux seek/scrub, avec ressources suivies à zéro. `benchmark/results/simulator-functional-pooled.local.json` et `final-functional-source-pooled.local.json` conservent ce run et sa provenance `486b12a…` / bundle `eb434d2…`. Ce sont des réexécutions ciblées ; le full59 n'a pas été rejoué sur ce build.
|
|
48
|
+
|
|
49
|
+
Ces résultats confirment le comportement exécuté. La mesure actuelle sur **cinq cas, trois répétitions**, a passé **15/15 répétitions** entre **16:40:14 et 16:43:27 UTC**, avec **63 exports sondés**. Un diagnostic distinct a ensuite réussi **3/3 répétitions de 100 exports**, soit **300 fichiers sondés**, entre **16:44:32 et 16:47:41 UTC**. [PERFORMANCE_SIMULATOR.md](PERFORMANCE_SIMULATOR.md) conserve ces résultats et [PERFORMANCE_SIMULATOR_INITIAL.md](PERFORMANCE_SIMULATOR_INITIAL.md) les mesures antérieures et observations de repos. L'horloge enregistrée est `performance.now` et les relevés mémoire sont demandés toutes les **100 ms** ; ce collecteur ajoute son propre coût et peut manquer des pics entre deux relevés. Les ressources suivies reviennent à zéro, mais le RSS augmente après les exports alternés ; au repos après le long run, il redescend de 551,375 à 353,453 Mio, sans attribution ni palier démontré. Les validateurs pixels/audio du catalogue restent indisponibles. Aucun A/B, résultat d'iPhone ou palier mémoire à long terme n'est démontré.
|
|
50
|
+
|
|
51
|
+
Après une nouvelle exécution native, consigner le `.xcresult` affiché par le script :
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
node scripts/benchmark-record-ios-simulator-verification.mjs RESULT.xcresult
|
|
55
|
+
node scripts/benchmark-inventory.mjs
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Le recorder refuse un résultat avec échec/skip, des noms XCTest manquants ou des sources modifiées après le début du build. Il ne relance pas le simulateur et ne transforme pas un ancien résultat en preuve des sources actuelles.
|
|
59
|
+
|
|
60
|
+
Les **quatorze fixtures communes réellement embarquées** et leur manifest ont été comparés aux sources : tailles et SHA-256 sont tous identiques. [fixture-bundle-verification.json](../benchmark/fixture-bundle-verification.json) conserve cette preuve du build Release du simulateur. La fixture JPEG 1279×719 réservée aux XCTest est distincte de ces quatorze médias du catalogue.
|
|
61
|
+
|
|
62
|
+
La stack réelle a identifié un accès à une SharedValue après transformation en worklet ; la fermeture liée à cette erreur a été corrigée, puis les réexécutions ont confirmé le montage et la restitution des réservations suivies. Le harness conserve `diagnostic` et `cleanupDiagnostic` séparément : opération, étape de montage, message et stack bornés. La cause d'origine survit à un échec secondaire de fermeture. Les 74 tests du harness incluent 17 régressions de validation du seek en lecture.
|
|
63
|
+
|
|
64
|
+
Les résultats sont dans **Documents/benchmark-results** du conteneur de l'application. Trouver le conteneur avec :
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
xcrun simctl get_app_container SIMULATOR_UDID com.seb.skiawebgpuvideo.test data
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Conserver les JSON et les logs d'échec avant de réinstaller l'exemple. Les rapports bruts portant des identifiants d'appareil peuvent rester dans `benchmark/results/*.local.json`, ignorés par Git et absents du paquet publié.
|
|
71
|
+
|
|
72
|
+
Le simulateur vérifie le comportement de la bibliothèque sur le runtime iOS et le GPU du Mac. Il ne qualifie ni les codecs matériels de l'iPhone, ni sa consommation mémoire, thermique ou énergétique. Les tests physiques et le A/B restent une étape ultérieure ; aucun A/B n'est lancé dans la correction fonctionnelle actuelle.
|
|
73
|
+
|
|
74
|
+
Les quatre traces natives de création/fermeture sont désormais derrière `RNSV_TRACE_LIFECYCLE`, désactivé en Release. Les avertissements `unrecognised property keys` viennent du codec HEVC Apple du simulateur (`VCPHEVC.videocodec`), également dans les XCTest HEVC qui passent. Aucun patch JavaScript n'est justifié ; isoler ce bruit du codec si nécessaire lors des mesures et garder une instrumentation identique dans les deux builds pour un futur A/B.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Migrating from React Native Skia Video
|
|
2
|
+
|
|
3
|
+
This library builds on the API of `@azzapp/react-native-skia-video` and its `batical` fork. Most composition and drawing concepts remain, while frame ownership and Skia texture interop change.
|
|
4
|
+
|
|
5
|
+
## Dependencies and native rebuild
|
|
6
|
+
|
|
7
|
+
Follow the [installation instructions](../README.md#installation) with the exact tested Skia, WebGPU, Reanimated, and Worklets versions. Remove the old Skia and Skia Video packages from the application before installing their replacements. Two native modules with the old and new video implementations must not coexist.
|
|
8
|
+
|
|
9
|
+
Replace imports:
|
|
10
|
+
|
|
11
|
+
| Previous package | New package |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `@shopify/react-native-skia` | `react-native-skia` |
|
|
14
|
+
| `@azzapp/react-native-skia-video` or your fork's package name | `react-native-skia-webgpu-video` |
|
|
15
|
+
|
|
16
|
+
Apply the required Skia patch in the consuming app, install pods on iOS, and rebuild native binaries. A JavaScript-only update cannot apply the native changes. See [upstream notes](UPSTREAM_NOTES.md) before changing the pinned Skia version.
|
|
17
|
+
|
|
18
|
+
## Frame drawing
|
|
19
|
+
|
|
20
|
+
Replace the hook names in your imports and call sites. The old names are not exported as compatibility aliases:
|
|
21
|
+
|
|
22
|
+
| Previous hook | Required replacement |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| `useVideoCompositionPlayer` | `useVideoComposition` |
|
|
25
|
+
| `useVideoPlayer` | `useVideoPlayback` |
|
|
26
|
+
|
|
27
|
+
Use `useVideoComposition` for a timeline and `useVideoPlayback` for a single video. Their composition options, playback controls and return values retain the same shape; migrating the hook names and frame drawing is required.
|
|
28
|
+
|
|
29
|
+
A native Metal or OpenGL texture handle is not a Dawn texture. Replace calls to `Skia.Image.MakeImageFromNativeTextureUnstable(frame.texture, ...)` with the library helper:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { drawVideoFrame } from 'react-native-skia-webgpu-video';
|
|
33
|
+
import type { FrameDrawer } from 'react-native-skia-webgpu-video';
|
|
34
|
+
|
|
35
|
+
const drawFrame: FrameDrawer = ({ canvas, frames, width, height }) => {
|
|
36
|
+
'worklet';
|
|
37
|
+
const frame = frames.clip;
|
|
38
|
+
if (frame) {
|
|
39
|
+
drawVideoFrame(canvas, frame, { x: 0, y: 0, width, height }, {
|
|
40
|
+
fit: 'contain',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Use `makeVideoFrameImage(frame)` if you need the image for another Skia operation. The library owns the returned image: do not independently call `dispose()` on it, change its native descriptor, or keep using it after its producer releases it. Application-owned synthetic frames need their own explicit ownership and cleanup.
|
|
47
|
+
|
|
48
|
+
The hooks still expose familiar play, pause, seek, looping, and readiness/error events. Compositions use seconds. `beforeDrawFrame` and `afterDrawFrame` run **per frame**; they are not session initialization/finalization callbacks.
|
|
49
|
+
|
|
50
|
+
## Preview and export
|
|
51
|
+
|
|
52
|
+
`useVideoComposition` renders a composition to a shared current image. Reuse the composition and `drawFrame` in `exportVideoComposition`. The [README example](../README.md#one-composition-preview-and-export) shows both.
|
|
53
|
+
|
|
54
|
+
- Composition sources use app-accessible local filesystem paths.
|
|
55
|
+
- Preview width/height are layout points; the drawing callback receives pixel dimensions. Export width/height are pixels.
|
|
56
|
+
- Use `lazyDecoders` for sequential timelines. A preview decode limit such as `maxLongSide` also limits source detail if reused during export; use separate settings when necessary.
|
|
57
|
+
- `copy` and `direct` remain API options with the same transport. iOS exports by drawing into the encoder's IOSurface-backed pool buffers; Android draws into AHardwareBuffers lent by the encoder when its AHardwareBuffer interop is available. Both fall back to CPU readback after a failed setup probe. Inspect `getVideoResourceStats().backend` for the transport instead of inferring it from the requested mode.
|
|
58
|
+
- Review application code that calls internal extractors or directly consumes native textures. Its frames must follow the new ownership protocol; the renamed hooks do not preserve the old texture representation.
|
|
59
|
+
|
|
60
|
+
## Audio
|
|
61
|
+
|
|
62
|
+
Audio options retain their existing meaning. A video composition item is silent by default; use `audio: true` or `audio: { volume: 0.8 }` to include its audio during playback and export. Separate `kind: 'audio'` items support music or voice-over. `useVideoPlayback` has its own `volume` option.
|
|
63
|
+
|
|
64
|
+
Audio is implemented on both native platforms, but the device runs so far (3.0.6, 3.4.4, 3.6.1 and 3.7.0) did not exercise audible output or validate audio synchronization. Test these paths with your application's actual sources before shipping.
|
|
65
|
+
|
|
66
|
+
## Memory and extensions
|
|
67
|
+
|
|
68
|
+
Set `configureVideoMemory({ maxBytes })` before allocating sessions. The budget covers tracked resources only; codecs and drivers can retain additional memory. A budget rejection does not silently reduce export dimensions.
|
|
69
|
+
|
|
70
|
+
On Android with the AHardwareBuffer interop (API 29+, 8-bit SDR H.264/HEVC at the encoded size), the codec writes into an `ImageReader`; WebGPU converts, crops and rotates each YUV buffer, imported once, into an independent Graphite snapshot after a checked GPU fence. Exports skip that snapshot: each clip's frame is converted into a texture of its own and sampled in place, as on iOS. Other sources render through the decoder's private EGL context into an RGBA AHardwareBuffer, or, without the interop, read owned RGBA pixels on the CPU and upload them. All of these avoid Skia's image-count raster-upload cache. CPU Java/JSI backing buffers remain accounted until their aliases and ART/Hermes owners are collected. See the [upstream cache notes](UPSTREAM_NOTES.md#android--éviter-le-cache-dimages-raster-du-provider) and the [3.6.1 verification](../migration/skia-3.6.1/verification.md).
|
|
71
|
+
|
|
72
|
+
The optional `createFrameProcessor` export factory creates a processor once per export. Its asynchronous `prepareFrame` runs at the requested composition timestamp and its `dispose` must finish all frame readers. Drive animated effects from that timestamp, not an independent display animation loop.
|
|
73
|
+
|
|
74
|
+
For GPU work, create `createVideoGpuScope` on the runtime that uses it. The Skia device is shared: do not destroy it or pass command encoders across runtimes. Track asynchronous work before starting it, remove images from consumers, and await `scope.dispose()`. CPU/ML inference needs its own tracked completion; a graphics fence does not finish unrelated inference.
|
|
75
|
+
|
|
76
|
+
If completion cannot be established after an error, the library can retain the affected state and reject later work to avoid releasing resources still in use. Zero tracked reservations alone is not proof that all process or GPU memory has been returned.
|
|
77
|
+
|
|
78
|
+
## Application validation
|
|
79
|
+
|
|
80
|
+
Check orientation, seek/loop behavior, source audio and added tracks, export dimensions and timestamps, cancellation, and repeated mount/export/unmount cycles on both platforms. Existing Skia patches, custom texture loaders, Skottie integrations, and application-specific effects require their own migration review.
|
|
81
|
+
|
|
82
|
+
See the [benchmark guide](BENCHMARKS.md) and [current iPhone comparison](PERFORMANCE_IPHONE_306_OPTIMIZATION.md) for what has actually been measured. Performance results are specific to their workloads and conditions.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Native memory investigation — Skia 3.0.6
|
|
2
|
+
|
|
3
|
+
Initial checkpoint: 2026-10-07; updated 2026-10-08. Base: `6c0c0556019b404e2601d85ee17dd876c1aad49a` (merged PR #3).
|
|
4
|
+
|
|
5
|
+
**The large export-related growth is reduced by reusing one frame worklet per export.** Clean physical-device comparisons and extended runs pass on both platforms. Memory still warms up and fluctuates; these bounded runs do not prove zero leaks in arbitrary long sessions. The provider ownership and export-recorder cache fixes were already on the baseline `main`; the change here addresses JavaScript-to-native worklet reconstruction.
|
|
6
|
+
|
|
7
|
+
## Baseline iPhone measurement — before the worklet fix
|
|
8
|
+
|
|
9
|
+
Physical iPhone 15 Pro, Release, Skia 3.0.6 / WebGPU 0.12.1. Two consecutive `4k-x8-lazy-direct` full workloads in one process, followed by 60 seconds idle. Each workload includes preview, seeks/scrubbing, looping, a 360-frame export, 25 churn cycles and 40 remounts.
|
|
10
|
+
|
|
11
|
+
Both cases passed. All 1,788 samples report nominal thermal state, normal power mode and an active app. Owned reservations, decoder and in-flight counters return to zero. These counters do not include every system/driver allocation.
|
|
12
|
+
|
|
13
|
+
| Checkpoint | Resident size (MiB) | Physical footprint (MiB) |
|
|
14
|
+
|---|---:|---:|
|
|
15
|
+
| After first workload | 207.05 | 310.53 |
|
|
16
|
+
| After second workload | 310.81 | 410.10 |
|
|
17
|
+
| After 60 seconds idle | 327.58 | 425.99 |
|
|
18
|
+
|
|
19
|
+
The idle measurement follows report serialization and is a different checkpoint from the workload's final sample. Memory stays nearly constant during that idle minute; it still grew between workloads. Most of the second workload's increase occurs around export. This is not proof of a leak in a particular component or of an eventual plateau.
|
|
20
|
+
|
|
21
|
+
Exports encode in 4.09 and 4.29 seconds, respectively. These are observations from this build, not a speed comparison. The workload's export has no audio track and does not establish audio correctness.
|
|
22
|
+
|
|
23
|
+
## Allocation tracing
|
|
24
|
+
|
|
25
|
+
Android tracing is opt-in for the standalone benchmark app:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
cd example/android
|
|
29
|
+
./gradlew :app:assembleRelease -PreactNativeArchitectures=arm64-v8a -PprofileMemory=true
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This enables the Android `profileable` manifest entry for that Release artifact. Ordinary builds omit it. Traced runs are for allocation attribution, not performance comparison with uninstrumented runs.
|
|
33
|
+
|
|
34
|
+
The first Android heapprofd capture (4 KiB sampling, 16 MiB client buffer) overflowed and disconnected at startup. Its attribution is invalid; do not use its partial allocations to explain workload growth. The retry uses 128 KiB sampling and a 64 MiB client buffer, without blocking the client. The retry also disconnected at startup (`heapprofd_client_error=2`); it is not a valid retained-allocation profile. Both full workload repetitions passed and the 60-second idle measurement finished (713.6 MiB total PSS, 858.2 MiB dumpsys total RSS), but this instrumented run is not a clean performance comparison.
|
|
35
|
+
|
|
36
|
+
The Android benchmark app was force-stopped after the final measurement. No benchmark app or owned Perfetto capture process remained. The investigation was paused at the user’s request on October 7 and resumed on October 8.
|
|
37
|
+
|
|
38
|
+
A separate iPhone Instruments Allocations recording is saved locally. Instruments emitted a duplicate dyld mapping warning during finalization. Statistics export succeeded; stack symbolication and attribution remain to be checked. Its totals must not be substituted for the clean measurement above.
|
|
39
|
+
|
|
40
|
+
Private raw traces, device identifiers, signed binaries and command logs remain in ignored benchmark results. Do not commit them.
|
|
41
|
+
|
|
42
|
+
## Investigation sequence and remaining limits
|
|
43
|
+
|
|
44
|
+
The Android heap captures were rejected as attribution evidence after their client errors were checked. The saved iPhone call tree then identified the worklet reconstruction path; a targeted fix and regression test were followed by clean Release measurements on both devices.
|
|
45
|
+
|
|
46
|
+
The fix is merged in [PR #4](https://github.com/batical/react-native-skia-webgpu-video/pull/4), commit `cd543506ab4fd3666350b3b2f632969d78447300`. The remaining qualification covers longer sessions, other devices and workloads, HDR/audio fidelity and application-specific 3D/ML resources. A valid Android allocation-stack capture remains unavailable; category PSS alone does not identify owners.
|
|
47
|
+
|
|
48
|
+
## 2026-10-08: export closure attribution and merged fix
|
|
49
|
+
|
|
50
|
+
The saved iPhone Allocations call tree attributes 32.44 MB (inclusive, as displayed by Instruments) on its heaviest persistent path to `RetainingSerializable<SerializableWorklet>::toJSValue`, followed by nested worklet/object reconstruction. These nested values must not be added together or equated with process footprint.
|
|
51
|
+
|
|
52
|
+
The export loop constructed its entire frame worklet inside the per-frame RN callback. Worklets 0.11.3 retains serialized worklets and caches serialization by function identity; constructing a fresh function for every image defeats that reuse. The corrected implementation creates one frame worklet per export and schedules that same function for subsequent frames. It preserves yielding between frames, progress delivery, cancellation, asynchronous processor waits and cleanup ordering. No global garbage collection or reduced video resolution is introduced.
|
|
53
|
+
|
|
54
|
+
A regression test submits two separate 360-frame exports, checks that each export reuses its frame closure while isolating the next export, and verifies resource disposal. All 196 Jest tests, TypeScript, package build and package validation pass. Android and iPhone Release builds succeed.
|
|
55
|
+
|
|
56
|
+
The first candidate iPhone run is excluded from the two-workload comparison: the first case failed during playback while the application became inactive/background, before export; the second case passed. The fresh comparison below replaces this interrupted attempt.
|
|
57
|
+
|
|
58
|
+
The Android profiler's error code 2 means `CLIENT_ERROR_INVALID_STACK_BOUNDS` in the [Perfetto protocol](https://github.com/google/perfetto/blob/main/protos/perfetto/trace/profiling/profile_packet.proto). The failed capture cannot attribute retained allocations. Clean Android memory comparisons can still run without that profiler.
|
|
59
|
+
|
|
60
|
+
### Candidate clean iPhone comparison
|
|
61
|
+
|
|
62
|
+
A fresh two-workload run passed both cases, with every memory sample nominal/normal/active. The native executable hash matches the baseline; the JavaScript bundle differs. This comparison uses the same full scenario, sampling period, fixtures, budget and physical device.
|
|
63
|
+
|
|
64
|
+
| Checkpoint | Before: physical footprint (MiB) | Candidate (MiB) |
|
|
65
|
+
|---|---:|---:|
|
|
66
|
+
| After first workload | 310.53 | 232.44 |
|
|
67
|
+
| After second workload | 410.10 | 258.36 |
|
|
68
|
+
| After report serialization and 60 s idle | 425.99 | 257.70 |
|
|
69
|
+
|
|
70
|
+
The second export no longer shows the large footprint increase: its surrounding settled checkpoints are 237.69 → 237.35 MiB. Full-workload growth is still 25.92 MiB between the first and second settled endpoints, so two successful cases do not establish an endurance plateau. The separate six-workload run below checks the longer trend.
|
|
71
|
+
|
|
72
|
+
### Candidate clean Android comparison
|
|
73
|
+
|
|
74
|
+
Two full workloads passed on the physical Pixel 8a. All 2,347 samples were nominal/normal/active. The candidate APK is a normal Release build without the allocation-profiling manifest flag. At 60 seconds idle, total PSS fell from 737.83 to 577.20 MiB (21.8%). Native Heap PSS fell from 142.26 to 79.51 MiB; Unknown PSS fell from 136.93 to 41.87 MiB. Category PSS is not live malloc size, and GL driver accounting is not a unique owner counter.
|
|
75
|
+
|
|
76
|
+
The two candidate exports encoded in 24.41 and 25.21 seconds, versus 28.81 and 29.40 seconds in the saved reference. This small sample is encouraging but does not establish a general speedup or presented FPS. The four-workload check below assesses the remaining growth.
|
|
77
|
+
|
|
78
|
+
### Six consecutive iPhone workloads
|
|
79
|
+
|
|
80
|
+
All six full workloads passed, each at nominal temperature, normal power and foreground execution. Settled physical footprint after each workload was **232.02, 252.81, 259.10, 268.41, 264.75 and 271.94 MiB**. After serializing the larger six-case report and waiting 60 seconds, footprint was **277.74 MiB**. This is consistent with a much flatter late-run trend (last three settled points span 7.19 MiB); it is not a proof of unlimited endurance or zero retention.
|
|
81
|
+
|
|
82
|
+
This run includes six 360-frame exports, 150 churn cycles and 240 remounts. No forced garbage collection, global cache purge, resolution reduction or larger memory quota was used. The iPhone application is stopped after the idle collector finishes.
|
|
83
|
+
|
|
84
|
+
### Four consecutive Android workloads
|
|
85
|
+
|
|
86
|
+
All four full workloads passed in nominal/normal/active conditions. Final settled PSS after each workload was **513.66, 566.49, 603.57 and 593.80 MiB**. Native Heap PSS readings at the same points were **55.70, 76.50, 92.92 and 82.16 MiB**, collected through `Debug.MemoryInfo.nativePss`; they are not live malloc allocation sizes. Both readings fall on the fourth workload, rather than growing every session.
|
|
87
|
+
|
|
88
|
+
The run includes four 360-frame exports, 100 churn cycles and 160 remounts. After 60 seconds idle, total PSS was **602.10 MiB**. The benchmark app was force-stopped after the final reading to release its screen-on request. Sanitized machine-readable comparisons and extended runs are in [stable-export-worklet-306.json](../benchmark/stable-export-worklet-306.json); raw device identifiers and traces remain private.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Comparaison Skia 2 / Skia 3 WebGPU
|
|
2
|
+
|
|
3
|
+
**Sur cet iPhone, le candidat Skia 3.0.3 réduit l’empreinte physique pendant la lecture 4K, mais augmente la mémoire des exports. Aucun gain global de vitesse ou d’absence de fuite n’est établi.** Ces mesures concernent exclusivement **Skia 3.0.3 / WebGPU 0.11.0**, pas les versions 3.0.5 ou 3.0.6.
|
|
4
|
+
|
|
5
|
+
Les quatre passages couvrent huit scénarios, trois répétitions chacun, dans des processus neufs : **48/48 statuts `passed` pour le candidat, 47/48 pour la référence**. Au premier passage de la référence, 733 des 811 échantillons thermiques sont `fair` ; une répétition HEVC 4K échoue au contrôle de lecture. Ce constat ne prouve pas que la température a causé cet échec. Les trois autres passages sont entièrement `nominal`, avec 24/24 scénarios chacun ; tous les échantillons des quatre passages sont au premier plan et en mode d’alimentation normal. **La paire BA est donc la référence d’interprétation ci-dessous** ; les chiffres AB et regroupés restent visibles avec leur réserve thermique.
|
|
6
|
+
|
|
7
|
+
- **Lecture H.264 4K :** dans BA, le pic d’empreinte physique passe de **511,28 à 361,88 Mio en copy (−29,2 %)** et de **709,00 à 371,61 Mio avec l’option direct (−47,6 %)**. Le RSS augmente pourtant de 23,8 % et 38,2 % : ces deux collecteurs mesurent des grandeurs différentes et doivent rester présentés ensemble.
|
|
8
|
+
- **Exports H.264 de 60 images en 640×360 :** dans BA, l’empreinte physique au pic augmente de **33,6 % en copy** et **47,8 % avec l’option direct**. Le pipeline prend 267,24 → 245,19 ms en copy et 222,60 → 242,48 ms en direct. Ces trois répétitions de petits exports ne suffisent pas à promettre une accélération générale.
|
|
9
|
+
- **Lecture :** les callbacks restent proches de **60/s**, malgré une capacité d’écran déclarée à 120 Hz. La borne du p95 de leur intervalle passe de 25 à 33,33 ms en 4K ; le callback de dessin est plus court, mais sa durée exclut une partie du pipeline et ne mesure pas le temps GPU ni les images effectivement affichées.
|
|
10
|
+
|
|
11
|
+
Les demandes `copy` et `direct` gardent la même interface publique. Le candidat utilise cependant une copie GPU à l’entrée et une lecture CPU des pixels composés à l’export (`gpuDirectExport: false`), tandis que la référence possède un chemin Metal direct. Les scénarios copy précèdent systématiquement les scénarios direct dans chaque processus : les caches déjà chargés empêchent d’attribuer leurs écarts au seul mode. Les variations A/B d’un même scénario sont interprétables avec ces routes documentées ; une comparaison causale copy/direct demanderait des processus séparés et un ordre inversé.
|
|
12
|
+
|
|
13
|
+
Les **24 sorties exportées du groupe comparable** — 12 par bibliothèque — ont toutes passé les contrôles du fichier : H.264, dimensions, 60 images, 30 fps, durée de deux secondes dans la tolérance prévue et horodatages monotones/exacts. Cela ne remplace pas la validation des pixels : les validateurs de scénario déclarés indisponibles restent tels quels. Le verdict strict **`failed` est conservé**, notamment pour les régressions mémoire, l’échec de lecture et les validations manquantes. Les compteurs internes du candidat reviennent à zéro aux 48 fins de scénario ; cela ne mesure ni les caches du pilote ni la mémoire totale et ne démontre pas l’absence de fuite.
|
|
14
|
+
|
|
15
|
+
Les exports mixtes sont étudiés séparément : le premier passage complet de neuf scénarios a produit un **SIGTRAP natif dans la référence**, dans `GrResourceCache::notifyARefCntReachedZero` pendant `readPixels` sur le thread d’export. Le candidat a terminé ce passage séparé à **27/27**, dont 60 exports mixtes ; ces résultats ne sont pas incorporés aux médianes des huit scénarios ci-dessous. Le test d’endurance de 300 exports de la référence a ensuite subi un second SIGTRAP, dans `GrResourceCache::removeResource` lors de la destruction d’une surface par le thread GC `hades`. Les deux piles concernent les ressources Ganesh, mais leur mécanisme causal précis reste inconnu. Les fichiers restants suggèrent respectivement le 17e export de la deuxième répétition et le 68e export de l’endurance ; aucun résultat partiel n’est inventé. [Premier rapport de crash](../benchmark/results/iphone-a1-baseline-303-crash-analysis.local.json), [rapport du test d’endurance](../benchmark/results/iphone-soak-baseline-303-crash-analysis.local.json). Le candidat a ensuite terminé les **300 exports** ; sa mémoire augmente entre les trois lots, et le collecteur de repos a expiré sans produire de relevé. Le [rapport d’endurance](PERFORMANCE_SOAK_IPHONE_303.md) conserve ces résultats et leurs limites ; aucun palier ni absence de fuite ne sont démontrés.
|
|
16
|
+
|
|
17
|
+
La source historique est restée propre au commit `334348ffeee8a4f6887fd1f663f8cf584f579911`. L’ordre ABBA, les identités de processus distinctes, les hachages des exécutables/bundles identiques par bibliothèque, les fixtures et les collecteurs ont été revérifiés : [preuve publique sans identifiant d’appareil](../benchmark/ab-iphone-303-verification.json). Cette référence emploie **Skia 2.10.1 / React Native 0.86.2**. Ces mesures portent sur la pile du benchmark. Les crashs et les chiffres ne se transposent pas automatiquement à une application utilisant d’autres versions ou workloads.
|
|
18
|
+
|
|
19
|
+
Comparaison mesurée : **failed** selon le comparateur strict. Cette qualification conserve les échecs, les régressions et les validations média manquantes.
|
|
20
|
+
|
|
21
|
+
Ancien : @azzapp/react-native-skia-video 0.10.1, Skia 2.10.1. Nouveau : react-native-skia-webgpu-video 0.1.0-alpha.0, Skia 3.0.3.
|
|
22
|
+
|
|
23
|
+
Environnement : device, iPhone16,1, ios 27.0.1, React Native 0.86.2, release, horloge performance.now.
|
|
24
|
+
|
|
25
|
+
Ordre : ancien (AB) → nouveau (AB) → nouveau (BA) → ancien (BA). Ordre A/B puis B/A vérifié, sans chevauchement.
|
|
26
|
+
|
|
27
|
+
## Résultats regroupés
|
|
28
|
+
|
|
29
|
+
Médianes des répétitions réussies ; les effectifs restent visibles. Les six répétitions éventuelles sont regroupées depuis deux processus par version et ne constituent pas six démarrages indépendants. Pour les tailles alternées, chaque répétition pèse autant après calcul de sa propre médiane.
|
|
30
|
+
|
|
31
|
+
| Scénario | Réussis ancien / nouveau | Pic RSS ancien / nouveau (MiB) | Écart RSS | RSS final ancien / nouveau (MiB) |
|
|
32
|
+
|---|---:|---:|---:|---:|
|
|
33
|
+
| Lecture continue H.264 1080p | 6/6 · 6/6 | 65.12 / 80.30 | +23.3 % | 65.11 / 80.30 |
|
|
34
|
+
| Lecture continue H.264 4K | 6/6 · 6/6 | 66.26 / 82.84 | +25.0 % | 66.24 / 82.80 |
|
|
35
|
+
| Lecture continue HEVC 4K | 5/6 · 6/6 | 66.39 / 85.95 | +29.5 % | 66.36 / 85.95 |
|
|
36
|
+
| steady-playback-h264-1080p30-audio-direct | 6/6 · 6/6 | 66.87 / 89.66 | +34.1 % | 66.83 / 89.64 |
|
|
37
|
+
| steady-playback-h264-4k30-direct | 6/6 · 6/6 | 67.06 / 93.31 | +39.1 % | 67.02 / 93.30 |
|
|
38
|
+
| steady-playback-hevc-4k30-direct | 6/6 · 6/6 | 67.28 / 96.77 | +43.8 % | 67.24 / 96.77 |
|
|
39
|
+
| Export H.264 | 6/6 · 6/6 | 78.78 / 124.47 | +58.0 % | 73.59 / 123.98 |
|
|
40
|
+
| encode-h264-direct | 6/6 · 6/6 | 74.35 / 155.81 | +109.6 % | 74.35 / 154.86 |
|
|
41
|
+
|
|
42
|
+
| Scénario | Pic empreinte physique ancien / nouveau (MiB) | Écart empreinte | Empreinte finale ancien / nouveau (MiB) |
|
|
43
|
+
|---|---:|---:|---:|
|
|
44
|
+
| Lecture continue H.264 1080p | 207.29 / 172.42 | -16.8 % | 133.40 / 67.31 |
|
|
45
|
+
| Lecture continue H.264 4K | 513.49 / 364.89 | -28.9 % | 387.00 / 170.53 |
|
|
46
|
+
| Lecture continue HEVC 4K | 479.86 / 366.87 | -23.5 % | 385.92 / 173.63 |
|
|
47
|
+
| steady-playback-h264-1080p30-audio-direct | 242.28 / 285.42 | +17.8 % | 201.43 / 177.01 |
|
|
48
|
+
| steady-playback-h264-4k30-direct | 709.10 / 374.61 | -47.2 % | 639.52 / 180.61 |
|
|
49
|
+
| steady-playback-hevc-4k30-direct | 694.56 / 377.87 | -45.6 % | 639.70 / 183.08 |
|
|
50
|
+
| Export H.264 | 206.72 / 277.79 | +34.4 % | 149.78 / 234.81 |
|
|
51
|
+
| encode-h264-direct | 191.63 / 309.33 | +61.4 % | 155.17 / 266.69 |
|
|
52
|
+
|
|
53
|
+
L’empreinte physique iOS provient de task_vm_info phys_footprint. Elle est mesurée séparément du RSS et reste indisponible lorsqu’aucun collecteur ne la fournit.
|
|
54
|
+
|
|
55
|
+
| Lecture | Callbacks/s ancien / nouveau | p95 CPU ancien / nouveau (ms) | p95 intervalle ancien / nouveau (ms) |
|
|
56
|
+
|---|---:|---:|---:|
|
|
57
|
+
| Lecture continue H.264 1080p | 59.97 / 59.95 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 25.00 |
|
|
58
|
+
| Lecture continue H.264 4K | 59.88 / 59.95 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
59
|
+
| Lecture continue HEVC 4K | 59.88 / 59.87 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
60
|
+
| steady-playback-h264-1080p30-audio-direct | 59.96 / 60.07 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 25.00 |
|
|
61
|
+
| steady-playback-h264-4k30-direct | 59.95 / 59.91 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
62
|
+
| steady-playback-hevc-4k30-direct | 59.95 / 59.95 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
63
|
+
|
|
64
|
+
| Export | Images | Pipeline ancien / nouveau (ms) | Écart pipeline | Total ancien / nouveau (ms) |
|
|
65
|
+
|---|---:|---:|---:|---:|
|
|
66
|
+
| Export H.264 640×360 | 60 | 257.19 / 243.41 | -5.4 % | 297.57 / 291.07 |
|
|
67
|
+
| encode-h264-direct 640×360 | 60 | 221.71 / 234.77 | +5.9 % | 263.26 / 283.55 |
|
|
68
|
+
|
|
69
|
+
Le pipeline couvre décodage, dessin et encodage, avant lecture des métadonnées. Le total inclut aussi la vérification et la suppression du fichier. La lecture mesure des callbacks, pas les images effectivement affichées ni le temps GPU ; les valeurs p95 sont les médianes des bornes supérieures du p95 par répétition, pas un p95 global recalculé.
|
|
70
|
+
|
|
71
|
+
Les scénarios steady-playback mesurent une lecture continue sans seek ; ils ne remplacent pas les scénarios historiques de seek, boucle et maintien d’image. Un échec historique de seek reste un échec fonctionnel distinct.
|
|
72
|
+
|
|
73
|
+
Les pics RSS sont échantillonnés, donc des bornes inférieures du vrai maximum. Le RSS final suit la pause de stabilisation prévue par le scénario ; les caches peuvent survivre et le processus poursuit les scénarios suivants. Ces chiffres ne démontrent ni fuite ni absence de fuite.
|
|
74
|
+
|
|
75
|
+
## Qualification et limites
|
|
76
|
+
|
|
77
|
+
Budget demandé : 512 MiB. Application ancien : non disponible ; nouveau : oui.
|
|
78
|
+
|
|
79
|
+
Les compteurs de ressources propres à la nouvelle bibliothèque restent indisponibles sur l’ancienne. Ils ne sont jamais remplacés par zéro et ne servent pas à comparer la mémoire totale. Mémoire GPU totale et tas natif séparé : non mesurés lorsque les collecteurs sont absents.
|
|
80
|
+
|
|
81
|
+
### AB — failed
|
|
82
|
+
|
|
83
|
+
- Library-owned memory budget enforcement differs between backends; requested limits are identical, enforcement availability is recorded
|
|
84
|
+
- Decode/render/encode transport changed; record the intended change and do not describe CPU readback results as GPU-only
|
|
85
|
+
- Lecture continue H.264 1080p : failed. Thermal state was non-nominal during the workload ; rssBytes peak regression
|
|
86
|
+
- Lecture continue H.264 4K : failed. Thermal state was non-nominal during the workload ; rssBytes peak regression
|
|
87
|
+
- Lecture continue HEVC 4K : failed. Baseline correctness / termination failure ; At least three successful repetitions per backend are required ; Thermal state was non-nominal during the workload ; rssBytes peak regression
|
|
88
|
+
- steady-playback-h264-1080p30-audio-direct : failed. Thermal state was non-nominal during the workload ; rssBytes peak regression ; physicalFootprintBytes peak regression
|
|
89
|
+
- steady-playback-h264-4k30-direct : failed. Thermal state was non-nominal during the workload ; rssBytes peak regression
|
|
90
|
+
- steady-playback-hevc-4k30-direct : failed. Thermal state was non-nominal during the workload ; rssBytes peak regression
|
|
91
|
+
- Export H.264 : failed. Baseline: Media validation unavailable: pixels ; Baseline: Media validation unavailable: presentation-timestamps ; Baseline: Media validation unavailable: actual-codec ; Candidate: Media validation unavailable: pixels ; Candidate: Media validation unavailable: presentation-timestamps ; Candidate: Media validation unavailable: actual-codec ; Thermal state was non-nominal during the workload ; rssBytes peak regression ; physicalFootprintBytes peak regression ; Pixel / audio / timestamp validation incomplete
|
|
92
|
+
- encode-h264-direct : failed. Baseline: Media validation unavailable: pixels ; Baseline: Media validation unavailable: presentation-timestamps ; Baseline: Media validation unavailable: actual-codec ; Candidate: Media validation unavailable: pixels ; Candidate: Media validation unavailable: presentation-timestamps ; Candidate: Media validation unavailable: actual-codec ; Thermal state was non-nominal during the workload ; rssBytes peak regression ; physicalFootprintBytes peak regression ; Pixel / audio / timestamp validation incomplete
|
|
93
|
+
|
|
94
|
+
### BA — failed
|
|
95
|
+
|
|
96
|
+
- Library-owned memory budget enforcement differs between backends; requested limits are identical, enforcement availability is recorded
|
|
97
|
+
- Decode/render/encode transport changed; record the intended change and do not describe CPU readback results as GPU-only
|
|
98
|
+
- Lecture continue H.264 1080p : failed. rssBytes peak regression
|
|
99
|
+
- Lecture continue H.264 4K : failed. rssBytes peak regression
|
|
100
|
+
- Lecture continue HEVC 4K : failed. rssBytes peak regression
|
|
101
|
+
- steady-playback-h264-1080p30-audio-direct : failed. rssBytes peak regression ; physicalFootprintBytes peak regression
|
|
102
|
+
- steady-playback-h264-4k30-direct : failed. rssBytes peak regression
|
|
103
|
+
- steady-playback-hevc-4k30-direct : failed. rssBytes peak regression
|
|
104
|
+
- Export H.264 : failed. Baseline: Media validation unavailable: pixels ; Baseline: Media validation unavailable: presentation-timestamps ; Baseline: Media validation unavailable: actual-codec ; Candidate: Media validation unavailable: pixels ; Candidate: Media validation unavailable: presentation-timestamps ; Candidate: Media validation unavailable: actual-codec ; rssBytes peak regression ; physicalFootprintBytes peak regression ; Pixel / audio / timestamp validation incomplete
|
|
105
|
+
- encode-h264-direct : failed. Baseline: Media validation unavailable: pixels ; Baseline: Media validation unavailable: presentation-timestamps ; Baseline: Media validation unavailable: actual-codec ; Candidate: Media validation unavailable: pixels ; Candidate: Media validation unavailable: presentation-timestamps ; Candidate: Media validation unavailable: actual-codec ; rssBytes peak regression ; physicalFootprintBytes peak regression ; Pixel / audio / timestamp validation incomplete
|
|
106
|
+
|
|
107
|
+
## Paire AB
|
|
108
|
+
|
|
109
|
+
| Scénario | Réussis ancien / nouveau | Pic RSS ancien / nouveau (MiB) | Écart RSS | RSS final ancien / nouveau (MiB) |
|
|
110
|
+
|---|---:|---:|---:|---:|
|
|
111
|
+
| Lecture continue H.264 1080p | 3/3 · 3/3 | 65.14 / 81.16 | +24.6 % | 65.13 / 81.14 |
|
|
112
|
+
| Lecture continue H.264 4K | 3/3 · 3/3 | 66.58 / 83.73 | +25.8 % | 66.56 / 83.73 |
|
|
113
|
+
| Lecture continue HEVC 4K | 2/3 · 3/3 | 66.66 / 86.72 | +30.1 % | 66.63 / 86.72 |
|
|
114
|
+
| steady-playback-h264-1080p30-audio-direct | 3/3 · 3/3 | 67.11 / 90.34 | +34.6 % | 67.08 / 90.33 |
|
|
115
|
+
| steady-playback-h264-4k30-direct | 3/3 · 3/3 | 67.30 / 94.06 | +39.8 % | 67.27 / 94.06 |
|
|
116
|
+
| steady-playback-hevc-4k30-direct | 3/3 · 3/3 | 67.55 / 97.78 | +44.8 % | 67.52 / 97.78 |
|
|
117
|
+
| Export H.264 | 3/3 · 3/3 | 79.30 / 123.98 | +56.4 % | 73.97 / 123.98 |
|
|
118
|
+
| encode-h264-direct | 3/3 · 3/3 | 74.64 / 156.69 | +109.9 % | 74.64 / 154.86 |
|
|
119
|
+
|
|
120
|
+
| Scénario | Pic empreinte physique ancien / nouveau (MiB) | Écart empreinte | Empreinte finale ancien / nouveau (MiB) |
|
|
121
|
+
|---|---:|---:|---:|
|
|
122
|
+
| Lecture continue H.264 1080p | 206.81 / 173.20 | -16.3 % | 132.38 / 68.89 |
|
|
123
|
+
| Lecture continue H.264 4K | 515.53 / 367.86 | -28.6 % | 385.30 / 171.64 |
|
|
124
|
+
| Lecture continue HEVC 4K | 495.70 / 370.30 | -25.3 % | 398.88 / 174.24 |
|
|
125
|
+
| steady-playback-h264-1080p30-audio-direct | 242.38 / 288.49 | +19.0 % | 201.36 / 177.72 |
|
|
126
|
+
| steady-playback-h264-4k30-direct | 709.24 / 377.38 | -46.8 % | 636.75 / 183.47 |
|
|
127
|
+
| steady-playback-hevc-4k30-direct | 709.39 / 380.78 | -46.3 % | 639.10 / 187.19 |
|
|
128
|
+
| Export H.264 | 175.64 / 279.20 | +59.0 % | 134.41 / 236.91 |
|
|
129
|
+
| encode-h264-direct | 176.02 / 312.30 | +77.4 % | 139.53 / 269.78 |
|
|
130
|
+
|
|
131
|
+
L’empreinte physique iOS provient de task_vm_info phys_footprint. Elle est mesurée séparément du RSS et reste indisponible lorsqu’aucun collecteur ne la fournit.
|
|
132
|
+
|
|
133
|
+
| Lecture | Callbacks/s ancien / nouveau | p95 CPU ancien / nouveau (ms) | p95 intervalle ancien / nouveau (ms) |
|
|
134
|
+
|---|---:|---:|---:|
|
|
135
|
+
| Lecture continue H.264 1080p | 59.96 / 59.96 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 25.00 |
|
|
136
|
+
| Lecture continue H.264 4K | 59.87 / 59.95 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
137
|
+
| Lecture continue HEVC 4K | 59.92 / 59.87 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
138
|
+
| steady-playback-h264-1080p30-audio-direct | 59.95 / 60.16 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 25.00 |
|
|
139
|
+
| steady-playback-h264-4k30-direct | 59.93 / 59.86 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
140
|
+
| steady-playback-hevc-4k30-direct | 59.95 / 59.97 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
141
|
+
|
|
142
|
+
| Export | Images | Pipeline ancien / nouveau (ms) | Écart pipeline | Total ancien / nouveau (ms) |
|
|
143
|
+
|---|---:|---:|---:|---:|
|
|
144
|
+
| Export H.264 640×360 | 60 | 247.15 / 242.08 | -2.0 % | 287.95 / 291.33 |
|
|
145
|
+
| encode-h264-direct 640×360 | 60 | 219.51 / 232.09 | +5.7 % | 260.41 / 279.86 |
|
|
146
|
+
|
|
147
|
+
## Paire BA
|
|
148
|
+
|
|
149
|
+
| Scénario | Réussis ancien / nouveau | Pic RSS ancien / nouveau (MiB) | Écart RSS | RSS final ancien / nouveau (MiB) |
|
|
150
|
+
|---|---:|---:|---:|---:|
|
|
151
|
+
| Lecture continue H.264 1080p | 3/3 · 3/3 | 65.09 / 79.77 | +22.5 % | 65.09 / 79.75 |
|
|
152
|
+
| Lecture continue H.264 4K | 3/3 · 3/3 | 66.25 / 82.05 | +23.8 % | 66.23 / 82.05 |
|
|
153
|
+
| Lecture continue HEVC 4K | 3/3 · 3/3 | 66.33 / 85.00 | +28.2 % | 66.30 / 85.00 |
|
|
154
|
+
| steady-playback-h264-1080p30-audio-direct | 3/3 · 3/3 | 66.61 / 88.67 | +33.1 % | 66.58 / 88.64 |
|
|
155
|
+
| steady-playback-h264-4k30-direct | 3/3 · 3/3 | 66.80 / 92.33 | +38.2 % | 66.72 / 92.33 |
|
|
156
|
+
| steady-playback-hevc-4k30-direct | 3/3 · 3/3 | 67.00 / 96.22 | +43.6 % | 66.97 / 96.22 |
|
|
157
|
+
| Export H.264 | 3/3 · 3/3 | 78.70 / 124.95 | +58.8 % | 73.31 / 123.98 |
|
|
158
|
+
| encode-h264-direct | 3/3 · 3/3 | 74.06 / 154.94 | +109.2 % | 74.06 / 154.86 |
|
|
159
|
+
|
|
160
|
+
| Scénario | Pic empreinte physique ancien / nouveau (MiB) | Écart empreinte | Empreinte finale ancien / nouveau (MiB) |
|
|
161
|
+
|---|---:|---:|---:|
|
|
162
|
+
| Lecture continue H.264 1080p | 207.77 / 171.06 | -17.7 % | 134.53 / 66.02 |
|
|
163
|
+
| Lecture continue H.264 4K | 511.28 / 361.88 | -29.2 % | 388.14 / 169.97 |
|
|
164
|
+
| Lecture continue HEVC 4K | 479.75 / 363.39 | -24.3 % | 385.92 / 172.94 |
|
|
165
|
+
| steady-playback-h264-1080p30-audio-direct | 242.19 / 281.70 | +16.3 % | 204.31 / 176.42 |
|
|
166
|
+
| steady-playback-h264-4k30-direct | 709.00 / 371.61 | -47.6 % | 639.52 / 179.55 |
|
|
167
|
+
| steady-playback-hevc-4k30-direct | 677.58 / 375.10 | -44.6 % | 639.74 / 179.44 |
|
|
168
|
+
| Export H.264 | 206.81 / 276.38 | +33.6 % | 164.94 / 232.72 |
|
|
169
|
+
| encode-h264-direct | 207.30 / 306.36 | +47.8 % | 170.81 / 263.60 |
|
|
170
|
+
|
|
171
|
+
L’empreinte physique iOS provient de task_vm_info phys_footprint. Elle est mesurée séparément du RSS et reste indisponible lorsqu’aucun collecteur ne la fournit.
|
|
172
|
+
|
|
173
|
+
| Lecture | Callbacks/s ancien / nouveau | p95 CPU ancien / nouveau (ms) | p95 intervalle ancien / nouveau (ms) |
|
|
174
|
+
|---|---:|---:|---:|
|
|
175
|
+
| Lecture continue H.264 1080p | 59.98 / 59.95 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 25.00 |
|
|
176
|
+
| Lecture continue H.264 4K | 59.89 / 59.96 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
177
|
+
| Lecture continue HEVC 4K | 59.71 / 59.86 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
178
|
+
| steady-playback-h264-1080p30-audio-direct | 59.97 / 59.97 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 25.00 |
|
|
179
|
+
| steady-playback-h264-4k30-direct | 59.95 / 59.96 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
180
|
+
| steady-playback-hevc-4k30-direct | 59.95 / 59.87 | ≤ 1.00 / ≤ 0.25 | ≤ 25.00 / ≤ 33.33 |
|
|
181
|
+
|
|
182
|
+
| Export | Images | Pipeline ancien / nouveau (ms) | Écart pipeline | Total ancien / nouveau (ms) |
|
|
183
|
+
|---|---:|---:|---:|---:|
|
|
184
|
+
| Export H.264 640×360 | 60 | 267.24 / 245.19 | -8.3 % | 307.18 / 290.81 |
|
|
185
|
+
| encode-h264-direct 640×360 | 60 | 222.60 / 242.48 | +8.9 % | 263.31 / 296.83 |
|
|
186
|
+
|
|
187
|
+
## Traçabilité
|
|
188
|
+
|
|
189
|
+
| Version / paire | Début UTC | Fin UTC | JSON SHA-256 |
|
|
190
|
+
|---|---|---|---|
|
|
191
|
+
| baseline / AB | 2026-10-07T07:44:15.822Z | 2026-10-07T07:46:27.608Z | 003d3f35182e1e065ed82a017495a4f8f1ee502cbfac71d812892e3ead83194e |
|
|
192
|
+
| candidate / AB | 2026-10-07T07:51:39.291Z | 2026-10-07T07:53:51.311Z | 7238e44ccf7bf1806df6f9de032d312a53dd75f959e3d29f4f214d4aecce0ba1 |
|
|
193
|
+
| candidate / BA | 2026-10-07T07:54:39.689Z | 2026-10-07T07:56:51.876Z | 810c896c05ac7ebe0bcec50887b54155ab5a9e0bf6ba0035dffe3660725b37fa |
|
|
194
|
+
| baseline / BA | 2026-10-07T07:57:33.980Z | 2026-10-07T07:59:45.784Z | 31f5251e0b2b396cc507253cc93398379cc6b06010c4bb2ac6a75f26ac91b1d1 |
|
|
195
|
+
|
|
196
|
+
Les fenêtres sont celles enregistrées par chaque application. Les fichiers JSON conservent les échantillons, les conditions thermiques, les résultats des vérifications et les mesures par répétition.
|