Add dynamic sampling to frame screenshots#56048
Closed
huntie wants to merge 1 commit intofacebook:mainfrom
Closed
Conversation
9ff647c to
303d30b
Compare
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 11, 2026
Summary: Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame visual snapshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. NOTE:⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). NOTE:⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
303d30b to
553a459
Compare
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 11, 2026
Summary: Pull Request resolved: facebook#56048 Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame visual snapshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. NOTE:⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). NOTE:⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
553a459 to
f2155ae
Compare
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 11, 2026
Summary: Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame visual snapshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. NOTE:⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). **Dynamic throttling algorithm** - Use a single `lastFrameBuffer` to store the most recently captured frame (bitmap + metadata) - Use a serial background thread (single-thread executor) for all encoding work - Use an atomic `encodingInProgress` flag to track encoding state - Always capture screenshots to `lastFrameBuffer` on every frame (even during encoding), replacing any previous waiting frame - When not encoding: start encoding the captured frame - When encoding finishes: loop back and check if buffer was refilled, encode that frame if present - Always emit frame timing events immediately (without screenshot) This ensures we don't queue up excessive encoding work while maintaining continuous frame timing data and guaranteeing the final settled state of animations is captured (tail-capture), minimizing the performance impact of recording on the device. NOTE:⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 11, 2026
Summary: Pull Request resolved: facebook#56048 Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame visual snapshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. NOTE:⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). **Dynamic throttling algorithm** - Use a single `lastFrameBuffer` to store the most recently captured frame (bitmap + metadata) - Use a serial background thread (single-thread executor) for all encoding work - Use an atomic `encodingInProgress` flag to track encoding state - Always capture screenshots to `lastFrameBuffer` on every frame (even during encoding), replacing any previous waiting frame - When not encoding: start encoding the captured frame - When encoding finishes: loop back and check if buffer was refilled, encode that frame if present - Always emit frame timing events immediately (without screenshot) This ensures we don't queue up excessive encoding work while maintaining continuous frame timing data and guaranteeing the final settled state of animations is captured (tail-capture), minimizing the performance impact of recording on the device. NOTE:⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
f2155ae to
57fe50b
Compare
Summary: Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame screenshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. **Algorithm** Uses `encodingInProgress` atomic flag with single-background-thread encoder and `lastFrameBuffer` for tail-capture: - **Not encoding:** Frame passes directly to encoder → emits with screenshot when done - **Encoding busy:** Frame stored in `lastFrameBuffer` for tail-capture → any replaced frame emits without screenshot - **Encoding done:** Clears flag early, then opportunistically encodes tail frame without blocking new frames - **Failed captures:** Emit without screenshot immediately Result: Every frame emitted exactly once. Encoding adapts to device speed. Settled animation state guaranteed captured. **Remaining work** -⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). -⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
57fe50b to
3a23a1e
Compare
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 12, 2026
Summary: Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame screenshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. **Algorithm** Uses `encodingInProgress` atomic flag with single encoding thread and `lastFrameBuffer` storage for tail-capture of the last frame before idling (to capture settled animation states): - **Not encoding:** Frame passes directly to encoder → emits with screenshot when done - **Encoding busy:** Frame stored in `lastFrameBuffer` for tail-capture → any replaced frame emits without screenshot - **Encoding done:** Clears flag early, then opportunistically encodes tail frame without blocking new frames - **Failed captures:** Emit without screenshot immediately Result: Every frame emitted exactly once. Encoding adapts to device speed. Settled animation state guaranteed captured. **Remaining work** -⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). -⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 12, 2026
Summary: Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame screenshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. **Algorithm** Uses `encodingInProgress` atomic flag with single encoding thread and `lastFrameBuffer` storage for tail-capture of the last frame before idling (to capture settled animation states): - **Not encoding:** Frame passes directly to encoder → emits with screenshot when done - **Encoding busy:** Frame stored in `lastFrameBuffer` for tail-capture → any replaced frame emits without screenshot - **Encoding done:** Clears flag early, then opportunistically encodes tail frame without blocking new frames - **Failed captures:** Emit without screenshot immediately Result: Every frame emitted exactly once. Encoding adapts to device speed. Settled animation state guaranteed captured. **Remaining work** -⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). -⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 12, 2026
Summary: Pull Request resolved: facebook#56048 Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame visual snapshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. NOTE:⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). **Algorithm** Uses `encodingInProgress` atomic flag with single-background-thread encoder and `lastFrameBuffer` for tail-capture: - **Not encoding:** Frame passes directly to encoder → emits with screenshot when done - **Encoding busy:** Frame stored in `lastFrameBuffer` for tail-capture → any replaced frame emits without screenshot - **Encoding done:** Clears flag early, then opportunistically encodes tail frame without blocking new frames - **Failed captures:** Emit without screenshot immediately Result: Every frame emitted exactly once. Encoding adapts to device speed. Settled animation state guaranteed captured. NOTE:⚠️ We do still typically lose a small region of pending frames at the end of a trace, but this is now more reasonable. A further fix (likely unnecessary) is to add lifecycle methods to await frame processing before responding to `Tracing.stop`. Changelog: [Internal] Differential Revision: D95987488
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Mar 12, 2026
Summary: Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events. **Motivation** 1. Prevents truncated trace data on slower devices (e.g. missing screenshots for the last 1/3 of the trace), with the tradeoff of some intermediate frame screenshot loss. 2. Reduces total recording overhead by freeing up device threads - prevents excessive encoding work from blocking or slowing down the UI and other app threads. **Algorithm** Uses `encodingInProgress` atomic flag with single encoding thread and `lastFrameBuffer` storage for tail-capture of the last frame before idling (to capture settled animation states): - **Not encoding:** Frame passes directly to encoder → emits with screenshot when done - **Encoding busy:** Frame stored in `lastFrameBuffer` for tail-capture → any replaced frame emits without screenshot - **Encoding done:** Clears flag early, then opportunistically encodes tail frame without blocking new frames - **Failed captures:** Emit without screenshot immediately Result: Every frame emitted exactly once. Encoding adapts to device speed. Settled animation state guaranteed captured. **Remaining work** -⚠️ This still does not yet solve crashes (OkHttp network chunk size overflow) for heavy frame data at a high FPS on fast devices (coming next). Changelog: [Internal] Reviewed By: rubennorte Differential Revision: D95987488
|
This pull request has been merged in d309cda. |
Collaborator
|
This pull request was successfully merged by @huntie in d309cda When will my fix make it into a release? | How to file a pick request? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
Update Android frame screenshot processing to skip screenshot capture when encoding is already in progress — now limited to a single background thread — while always emitting frame timing events.
Motivation
Algorithm
Uses
encodingInProgressatomic flag with single encoding thread andlastFrameBufferstorage for tail-capture of the last frame before idling (to capture settled animation states):lastFrameBufferfor tail-capture → any replaced frame emits without screenshotResult: Every frame emitted exactly once. Encoding adapts to device speed. Settled animation state guaranteed captured.
Remaining work
Tracing.stop.Changelog: [Internal]
Differential Revision: D95987488