Performance: three libse micro-optimizations (verified with BenchmarkDotNet)#12575
Merged
Conversation
…DotNet)
- LanguageAutoDetect: cache compiled regexes for the word-count
patterns. One detection probes ~40+ large alternation patterns -
far more than the built-in regex cache holds (Regex.CacheSize is
15), so every AutoDetectGoogleLanguage call re-parsed every pattern
(subtitle open, live spell check arming, speech to text setup).
Detection sweep: 494 ms -> 8.6 ms (~58x), allocations 1049 KB ->
127 KB.
- AssaResampler: route the per-line tag regexes through the existing
pattern cache. The Fix*Parameters/FixTagWithNumber methods built
6-8 fresh Regex instances per dialogue line during resampling while
a GetCachedRegex cache already existed in the class. One tagged
line: 20.6 us -> 3.1 us (~6.7x), allocations 42 KB -> 4.6 KB.
- SubtitleFormat.FriendlyName: cache the "$"{Name} ({Extension})""
interpolation, which allocated on every access and is looped over
all ~300 formats in FromName/GetSubtitleFormatByFriendlyName. The
cache is reference-guarded on Extension because MPlayer2/TimedText
extensions are settings-dependent. Lookup scan allocations:
22 KB -> 0.5 KB (-98%).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Three micro-optimizations, each verified with BenchmarkDotNet (v0.15.8, .NET 10): the "Old" column is the previous code's kernel replicated verbatim in the bench harness; "New" calls the actual patched libse code.
1.
LanguageAutoDetect— cache compiled regexesOne detection probes ~40+ large alternation patterns (hundreds of words each) via static
Regex.Matches. That exceeds the built-in regex cache (Regex.CacheSize= 15), so everyAutoDetectGoogleLanguagecall re-parsed every pattern — on every subtitle open, live-spell-check re-arm, and speech-to-text setup. Now cached in aConcurrentDictionarywithRegexOptions.Compiled(bounded — the word lists are fixed for the app lifetime).GetCountContainsgets the same treatment.2.
AssaResampler— stop compiling regexes per lineFixMethodTwoParameters/FourParameters/SixParametersFourActive/FixTagWithNumberbuiltnew Regex("\\\\" + tag + …)per call — 6–8 regex compiles per dialogue line during resolution resampling — even though the class already had aGetCachedRegexpattern cache these four sites bypassed. They now use it. (The "New" benchmark runs the full realResampleOverrideTagsPositionincluding the value rewriting the "Old" kernel skips, so the real gain is understated if anything.)3.
SubtitleFormat.FriendlyName— cache the interpolationFriendlyName => $"{Name} ({Extension})"allocated a new string on every access, andFromName/GetSubtitleFormatByFriendlyNameloop it over all ~300 formats. Now cached per instance — reference-guarded onExtension, becauseMPlayer2/TimedText*extensions are settings-dependent and a naive cache would go stale when those settings change (constants are interned, settings values keep their instance until changed, so the guard is exact). The win here is allocation elimination; time is dominated by the string comparisons either way.🤖 Generated with Claude Code