Speed up StartsAndEndsWithTag with allocation-free span checks - #13381
Merged
niksedk merged 3 commits intoAug 9, 2026
Conversation
Replace the per-call prefix/suffix string concatenations ("- " + startTag,
endTag + ".", etc.) with two small loops that skip leading dash/dot/space
and trailing punctuation, then compare the tags via ReadOnlySpan without
allocating. Also collapse double spaces with FixExtraSpaces instead of a
repeated string.Replace loop.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes Utilities.StartsAndEndsWithTag in libse by replacing allocation-heavy string concatenations and repeated Replace loops with allocation-free ReadOnlySpan<char> prefix/suffix checks and simple character-skipping loops. This should reduce GC pressure and improve throughput for common subtitle-tag patterns (e.g., dialog dashes and trailing punctuation around HTML tags).
Changes:
- Reworked tag detection to skip leading dialog markers (
' ','.','-') before checkingstartTagvia spans. - Reworked end detection to trim common trailing punctuation/whitespace (
'.','!','?','-',' ') before checkingendTagvia spans. - Removed the previous per-call construction of multiple prefix/suffix strings and the repeated double-space replacement loop.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
7 tasks
- Add doc comment stating the skip characters must not overlap the tags - Guard the trailing-punctuation scan with startIndex instead of 0 - Add tests covering both the old accepted forms and the variants the character-skip approach additionally accepts (leading ellipsis/dots, runs of trailing punctuation), plus FixInvalidItalicTags integration tests pinning the resulting italic merges 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.
Summary
Utilities.StartsAndEndsWithTagto skip leading dialog dashes/dots/spaces and trailing punctuation with two small character loops, then match the tags withReadOnlySpan<char>comparisons - removes the per-call prefix/suffix string concatenations ("- " + startTag,endTag + ".", ...) and thewhile (text.Contains(" "))double-space collapse loop (no longer needed, since the character skip handles repeated spaces directly)...without a dialog dash, runs of trailing punctuation like?!) - this widens the italic-merge behavior inFixInvalidItalicTagsslightly, and is now pinned deliberately by testsUtilitiesStartsAndEndsWithTagTestcovers the old accepted forms and the newly accepted variants; twoHtmlUtilTestintegration tests pin the resulting italic mergesBenchmark
BenchmarkDotNet v0.14.0, Windows 11, i7-13700, .NET 10.0.10 (X64 RyuJIT AVX2). Old = previous implementation, New = this PR. Tags:
<i>/</i>.<i>Hello there, how are you?</i>- <i>Hello there, how are you?</i>He said <i>hello</i> to me.Hello there, how are you today?Test plan
dotnet test tests/libse/LibSETests.csproj- 977 passed (includes the newStartsAndEndsWithTagunit tests andFixInvalidItalicTagsintegration tests)🤖 Generated with Claude Code