Skip to content

Skip the copy in writeRbsp when a frame needs no escaping - #2184

Merged
lukasIO merged 2 commits into
mainfrom
lukas/faster-write-rbsp
Oct 27, 2026
Merged

lukasIO merged 2 commits into
mainfrom
lukas/faster-write-rbsp

Conversation

@lukasIO

@lukasIO lukasIO commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

The E2EE worker calls writeRbsp on every encrypted H.264 and H.265 frame on the sender. It adds emulation prevention bytes so that the ciphertext never contains a start code. Today the function pushes every byte into a JS array and then copies that array into a Uint8Array. On a 500 KB keyframe this takes about 2.2 ms, but AES-GCM takes about 0.09 ms. We found this while working on #2181.

Change

writeRbsp scans the input once and records each index that needs an emulation prevention byte. If there are none, it returns the input unchanged. This is the case for almost every encrypted frame, because random ciphertext rarely has two zeros followed by a byte <= 3. If there are escapes, it allocates the output once and copies the runs between the escapes with Uint8Array.set. The output and the wire format do not change. parseRbsp does not change, because the receiver calls it only after needsRbspUnescaping finds an escape.

Verified

  • npx vitest run src/e2ee passes. The new src/e2ee/utils.test.ts checks known escaped sequences: no escape, one escape, runs of zeros, and trailing zeros. It also checks that the function returns the same instance when nothing needs escaping.
  • The old and new functions return the same bytes on 20,005 inputs: random bytes, inputs with many zeros, and all-zero buffers.
  • Benchmark on random data, Node 24.22.1, median of 200 runs:
Frame size Before After
10 KB 0.027 ms 0.010 ms
50 KB 0.260 ms 0.049 ms
150 KB 0.635 ms 0.148 ms
500 KB 2.218 ms 0.530 ms

🤖 Generated with Claude Code

Find the escape points first, return the input when there are none, and
otherwise copy the runs between them with Uint8Array.set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lukasIO lukasIO self-assigned this Oct 25, 2026
@changeset-bot

changeset-bot Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 75af414

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
livekit-client Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size
dist/livekit-client.esm.mjs 115.96 KB (0%)
dist/livekit-client.umd.js 125.25 KB (-0.09% 🔽)
dist/core/core.mjs 78.65 KB (0%)

Comment thread src/e2ee/utils.ts Outdated
* Returns `data_in` itself when nothing needs escaping, which is the case for almost
* every encrypted frame. Callers must not mutate the result in place.
*/
export function writeRbsp(data_in: NonSharedUint8Array): NonSharedUint8Array {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: data_in should probably be dataIn?

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lukasIO
lukasIO merged commit 57cc9ea into main Oct 27, 2026
5 checks passed
@lukasIO
lukasIO deleted the lukas/faster-write-rbsp branch October 27, 2026 07:36
@github-actions github-actions Bot mentioned this pull request Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants