Skip to content

[Repo Assist] perf: StringBuilder in CSS readString; AsSpan in JsonStringEncodeTo on .NET 6+#1737

Draft
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/perf-css-readstring-json-asspan-2026-04-12-38697cfb279b5cbe
Draft

[Repo Assist] perf: StringBuilder in CSS readString; AsSpan in JsonStringEncodeTo on .NET 6+#1737
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/perf-css-readstring-json-asspan-2026-04-12-38697cfb279b5cbe

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

Two small performance improvements eliminating unnecessary allocations in hot paths:

1. HtmlCssSelectors.fsreadString uses StringBuilder

The recursive readString function was accumulating chars by string concatenation (acc + c.ToString()), allocating a new string at every step — O(n²) total allocations for a CSS selector token of length n.

Fix: replaced the string accumulator with a System.Text.StringBuilder, with a thin non-recursive readString wrapper keeping all 13 call sites unchanged.

2. JsonValue.fsJsonStringEncodeTo uses AsSpan on .NET 6+

JsonStringEncodeTo was using value.Substring(start, len) to flush runs of unescaped characters to a TextWriter, allocating a temporary string. On .NET 6+ (net8.0 target), TextWriter.Write(ReadOnlySpan<char>) is available and avoids this allocation entirely. The netstandard2.0 path keeps Substring.

Trade-offs

  • Both changes are pure performance improvements with no semantic change.
  • The #if NETSTANDARD2_0 / #else guard adds a small amount of conditional code; the project already targets both netstandard2.0 and net8.0.

Test Status

Build and full test suite pass:

  • ✅ Format check (Fantomas)
  • ✅ Build (netstandard2.0 + net8.0)
  • ✅ All tests pass (2909+ core, 489 design-time, 292 integration, 2 reference)

Generated by 🌈 Repo Assist, see workflow run. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@7ee2b60744abf71b985bead4599640f165edcd93

…n .NET 6+

- HtmlCssSelectors: replace O(n²) string concatenation in readString with
  StringBuilder accumulator, reducing allocations for CSS selector parsing
- JsonValue: use TextWriter.Write(ReadOnlySpan<char>) instead of Substring
  in JsonStringEncodeTo when targeting .NET 6+ (NETSTANDARD2_0 fallback kept)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants