Speed up MKV subtitle open: cache parsed clusters + VINT lookup table#11397
Merged
Conversation
GetSubtitle is called three times in the PGS/BluRay open flow on the same MatroskaFile instance — once to populate the track-picker preview (TrackChanged), once via ParseBluRaySupFromMatroska for the cue thumbnails, and once via LoadBluRaySubFromMatroska to feed the OCR window. Each call walked every cluster in the file, so for multi-GB Blu-ray rips the file was read in full three times. Return the previously parsed list when the requested track matches the last one, so the cluster scan happens at most once per track per MatroskaFile instance. Different tracks still invalidate the cache, and the Count>0 guard avoids caching empty results. Fixes #11374 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ReadVariableLengthUInt is called twice per element read on every cluster walk. The length-detection portion (counting leading zeros of the first byte) was an 8-iteration mask/shift loop. A 256-entry lookup table is ~5x faster in isolation (measured: 5.19us -> 1.03us per 4096 bytes on M4, BenchmarkDotNet 0.14.0). Whole-scan wall-clock impact is small — I/O dominates — but the change is purely local and has no allocations. Existing fallthrough for invalid VINT first byte (0x00) is preserved by collapsing the -1 (EOF) and 0 (invalid) checks into a single guard, then checking the table result for 0. Co-Authored-By: Claude Opus 4.7 (1M context) <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.
Summary
Two MatroskaFile changes that reduce the time to open a Blu-ray-rip MKV with PGS subtitles. The first fixes #11374 directly; the second is a small follow-on perf win in the same hot path.
1. Cache parsed cluster data per track in
MatroskaFile.GetSubtitleGetSubtitleis called three times on the same instance during the PGS/BluRay open flow — once inPickMatroskaTrackViewModel.TrackChanged(PickMatroskaTrackViewModel.cs:227), once inBluRaySupParser.ParseBluRaySupFromMatroska(BluRaySupParser.cs:467) for the cue preview thumbnails, and once inBluRayHelper.LoadBluRaySubFromMatroska(BluRayHelper.cs:21) to feed the OCR window. Each call walked every cluster in the file (ReadSegmentCluster), so for multi-GB Blu-ray-rip MKVs the file was effectively read in full three times.The infrastructure for caching was already present —
_subtitleRipand_subtitleRipTrackNumberare existing fields — butGetSubtitleunconditionallyClear()ed the list every call. The fix returns the cached list when the requested track matches the last one. Different tracks still invalidate the cache (the existingtrackNumbermismatch path is unchanged), and theCount > 0guard avoids caching empty results from malformed/empty tracks.progressCallbackisnullat every BluRay call site, so skipping it on cache hits is a no-op for the existing flows.On Windows, the OS file cache hides most of the cost of the second/third pass. macOS users with Blu-ray-rip MKVs that exceed the unified buffer cache feel it as a multi-minute open; that should now be one cluster-walk instead of three.
Fixes #11374
2. Replace VINT length mask/shift loop with a 256-entry lookup table
ReadVariableLengthUIntis called twice per element read on every cluster walk. The length-detection portion (counting leading zeros of the first byte) was an 8-iteration mask/shift loop. A 256-entry lookup table replaces it.Measured with BenchmarkDotNet 0.14.0 on Apple M4, .NET 10, 4096 first-bytes per op:
~5× faster in isolation. Whole-scan wall-clock impact is small — I/O dominates — but the change is purely local, has no allocations, and is on the hottest path in the file.
Test plan
.mkvwith a single PGS subtitle track and proceed through to the OCR window — confirm no behavior change..mkvwith multiple subtitle tracks; click between tracks in the picker; export a track; click OK to OCR. Confirm previews/exports match the selected track (cache invalidates on track switch)..mkvwith a text-based track (SRT/SSA in MKV) — confirm the picker preview and final import are unchanged.LibSETests367 tests pass.🤖 Generated with Claude Code