Skip to content

perf: sort scoped variable cache keys without localeCompare - #754

Merged
Brentlok merged 1 commit into
uni-stack:mainfrom
alexa-endpoints:perf/scoped-variables-code-unit-sort
Oct 27, 2026
Merged

Brentlok merged 1 commit into
uni-stack:mainfrom
alexa-endpoints:perf/scoped-variables-code-unit-sort

Conversation

@dlebedynskyi

@dlebedynskyi dlebedynskyi commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

buildScopedVariablesContext sorts the merged variables with localeCompare to build the native style cache key. On Hermes for Android, every localeCompare call creates and frees a Java Collator through JNI, so this sort costs far more than it looks.

The key only needs the same order every time, and CSS custom property names are ASCII, so this sorts by code unit instead. The key's text can order names that differ in case differently from before, but the same variables always give the same key, and only the in-memory style cache reads it.

Measured

Release Hermes build on two low-end Android devices, ScopedVariables context with 60 variables (an app theme plus a component's own):

Before After
localeCompare calls per build 354 0
Context build, device A (median) 9.9 ms 0.45 ms
Context build, device B (median) 10.3 ms 0.42 ms

One localeCompare took 73-82 µs there, against 0.3 µs for a code-unit comparison. In an isolated benchmark the sort alone took 23-26 ms per build, and 47 ms on the little cores.

Tests

  • New native test: the key is the same for the same variables passed in either order, and building it doesn't call localeCompare. It fails on main in both Jest projects and passes with this change.
  • Ran the CI steps locally (build, type checks, lint, format, circular check, native 568, web 56, e2e 9, types), and exported apps/expo-example for iOS, Android and web, built apps/vite-example, and bundled apps/bare.

Summary by CodeRabbit

  • Bug Fixes
    • Scoped variable maps now produce consistent cache keys regardless of entry order, helping equivalent configurations share the same cached result. Key generation also no longer depends on locale-specific string comparison.

buildScopedVariablesContext sorts the merged variables with localeCompare
to build the cache key. On Hermes for Android, each localeCompare call
creates and frees a Java Collator through JNI, so a ScopedVariables with
60 variables made 354 calls and took about 10 ms to build on low-end
Android devices.

The key only needs the same order every time, and CSS custom property
names are ASCII, so sort by code unit instead. The key's text can change
order for names that differ in case, but it stays the same for the same
variables, and only the native style cache reads it. On the same devices
the build dropped to about 0.4 ms.
@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 616ba4ed-3fee-4be1-803a-f7df73a7e340
Commits

Reviewing files that changed from the base of the PR and between a6eb8ae and b14bccc.

Files selected for processing: 2
  • packages/uniwind/src/components/ScopedVariables/utils.ts
  • packages/uniwind/tests/native/components/scoped-variables.test.tsx

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Walkthrough

Scoped variable cache keys now sort entries by JavaScript code-unit order. A test checks that maps with different insertion orders produce the same key and that key generation does not call localeCompare.

Changes: Scoped variable cache key

Layer / File(s) Summary
Cache key sorting and validation
packages/uniwind/src/components/ScopedVariables/utils.ts, packages/uniwind/tests/native/components/scoped-variables.test.tsx
The cache key sorts entries using direct code-unit comparisons. The test checks equivalent maps with different insertion orders and verifies that localeCompare is not called.

Priority: Low

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Refactor

Suggested reviewers: brentlok

Merge Risk: Minimal · up to b14bc

The cache-key ordering change has no identified merge-blocking issue; merge after normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main performance change: removing localeCompare from scoped variable cache-key sorting.
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within survi…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 2 files.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Low impact] The PR appears safe to merge.

Summary

Replaces localeCompare with code-unit comparisons when building scoped-variable cache keys.

  • Scoped-variable contexts build cache keys without locale collation.

Reviews (1) · Last reviewed commit: "perf: sort scoped variable cache keys wi..." · Reviewed by Greptile

@Brentlok
Brentlok merged commit 848144c into uni-stack:main Oct 27, 2026
3 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🚀 This pull request is included in v1.13.1. See Release v1.13.1 for release notes.

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