Repository navigation
perf(wasm): Load ICU break dictionaries on demand - #26055
Draft
MartinZikmund wants to merge 4 commits into
Draft
MartinZikmund wants to merge 4 commits into
MartinZikmund wants to merge 4 commits into
Conversation
The uno.icu data embedded in every WebAssembly app is 5.5 MB (2.46 MB brotli), 2.0 MB of which are the break dictionaries that only Thai, Lao, Khmer, Myanmar and CJK text consults, and 0.4 MB locale data that break iteration never reads. The build now splits it: the app embeds the brkitr rules and *.icu tables (72 KB brotli) and deploys the dictionaries as an app asset. Uno.UI registers them with udata_setCommonData the first time text in those scripts is laid out, then invalidates the waiting text. Break results with both packages are identical to the full data (1560 samples over 26 locales and 4 break types). Blank app: Blank.wasm 2.53 MB -> 134 KB brotli. Opt out with UnoWasmIcuDictionariesOnDemand=false. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TXMNu2RupRy4QPFGK2cmij
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TXMNu2RupRy4QPFGK2cmij
The split rewrote its outputs on every build, and a newer embedded resource recompiles the app. Skip when both outputs are up to date. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TXMNu2RupRy4QPFGK2cmij
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TXMNu2RupRy4QPFGK2cmij
Comment on lines
+48
to
+52
| catch (Exception e) | ||
| { | ||
| Log.LogError($"Failed to split the ICU data {SourcePath}: {e.Message}"); | ||
| return false; | ||
| } |
Comment on lines
+92
to
+95
| catch (Exception e) | ||
| { | ||
| typeof(ICU).LogError()?.Error($"Failed to load the ICU break dictionaries from {uri}; Thai, Lao, Khmer, Myanmar and CJK text will break without them.", e); | ||
| } |
| try | ||
| { | ||
| var (startupPath, dictionariesPath) = RunTask(folder); | ||
| var stamp = File.GetLastWriteTimeUtc(Path.Combine(folder.FullName, "icudt.dat")).AddMinutes(1); |
| new IcuDataSplitTask_v0 | ||
| { | ||
| BuildEngine = new RecordingBuildEngine(), | ||
| SourcePath = Path.Combine(folder.FullName, "icudt.dat"), |
|
|
||
| private static (string Startup, string Dictionaries) RunTask(DirectoryInfo folder) | ||
| { | ||
| var source = Path.Combine(folder.FullName, "icudt.dat"); |
| { | ||
| BuildEngine = new RecordingBuildEngine(), | ||
| SourcePath = source, | ||
| StartupOutputPath = Path.Combine(folder.FullName, "out", "icudt.dat"), |
| BuildEngine = new RecordingBuildEngine(), | ||
| SourcePath = source, | ||
| StartupOutputPath = Path.Combine(folder.FullName, "out", "icudt.dat"), | ||
| DictionariesOutputPath = Path.Combine(folder.FullName, "out", "icudt-dict.dat"), |
Contributor
|
The build 243711 found UI Test snapshots differences: Details
|
2 of 5 tasks
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.
GitHub Issue: closes #26049
PR Type:
✨ Feature
What changed? 🚀
uno.icu-wasmembeds a 5.5 MBicudt.dat(2.46 MB brotli) in every WebAssembly app, of which 2.0 MB are the break dictionaries that only Thai, Lao, Khmer, Myanmar and CJK text uses.IcuDataSplitTask+_UnoSplitIcuDictionaries, browserwasm heads only): the head embeds the brkitr rules and*.icutables (72 KB brotli). The dictionaries are deployed asms-appx:///Uno.UI/icu/icudt-dict.dat, excluded from the PWA precache, plus a tiny resource naming that URI.UnicodeText.ICU.Dictionaries.cs): the first time text in those scripts is laid out, Uno fetches the dictionaries, registers them withudata_setCommonData, drops cached break iterators and invalidates the waiting text through the existingIFontCacheUpdateListenerpath.UnoWasmIcuDictionariesOnDemand=false.Blank app:
Blank.wasm2.53 MB → 134 KB brotli. On 4G (9 Mbps / 85 ms) this alone took visual-ready from 11.22 s to 9.42 s.Validation:
Given_IcuDataSplitTask(4), including an up-to-date check so incremental builds don't recompile.Measurements
Blank.wasm, brotli)On-demand dictionaries: 2.02 MB brotli, fetched only for Thai/Lao/Khmer/Myanmar/CJK text (0 bytes for this app).
How this was measured
Blank
dotnet new unoapp(Skia,net10.0-browserwasm, Release publish), built twice from the same tree: with all six startup PRs (#26054–#26059) plusUnoXamlResourcesTrimming, and with only this PR's change removed. Both builds were served by the same static server (brotli q11, immutable caching for fingerprinted files) and loaded cold in headless Chrome, runs interleaved. "Visually ready" is the first CDP screencast frame identical to the settled final frame. 4G = 9 Mbps down, 85 ms RTT (CDP emulation). Values are medians with (min–max). A difference is only claimed where the ranges don't overlap. Rig: Playwright + Node, available on request.PR Checklist ✅
Screenshots Compare Test Runresults.Open for discussion: the long-term home of the split is uno.icu (two data packages built with icupkg). This PR splits the existing package at build time, so it works with the current uno.icu release.
🤖 Generated with Claude Code
https://claude.ai/code/session_01TXMNu2RupRy4QPFGK2cmij