Skip to content

[Repo Assist] improve: use SearchValues(char) in ShellQuoting.NeedsQuoting for SIMD metachar scan#182

Merged
shanselman merged 1 commit intomasterfrom
repo-assist/improve-shellquoting-search-values-2026-04-19-6661ff63fb4feb01
Apr 20, 2026
Merged

[Repo Assist] improve: use SearchValues(char) in ShellQuoting.NeedsQuoting for SIMD metachar scan#182
shanselman merged 1 commit intomasterfrom
repo-assist/improve-shellquoting-search-values-2026-04-19-6661ff63fb4feb01

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

🤖 This is an automated PR from Repo Assist.

Summary

Replaces the per-character foreach + IsShellMetachar switch in ShellQuoting.NeedsQuoting with System.Buffers.SearchValues<char>, which builds a vectorized lookup structure at startup and uses IndexOfAny to scan for metacharacters in a single SIMD pass.

Root cause / motivation

NeedsQuoting is called on every argument in every system.run / system.run.prepare invocation. The former implementation iterated character-by-character through a 25-arm switch expression. On .NET 8+, SearchValues<char> uses SSE2/AVX2 instructions to check multiple characters against a lookup bitmap simultaneously — significantly faster for typical argument lengths.

Changes

File Change
ShellQuoting.cs Add using System.Buffers; add static readonly SearchValues<char> s_shellMetachars (same 25-char set as IsShellMetachar); replace NeedsQuoting body with arg.AsSpan().IndexOfAny(s_shellMetachars) >= 0; remove now-unused IsShellMetachar private helper

Net diff: 9 insertions / 16 deletions — net −7 lines while preserving identical semantics.

Metacharacter set preserved (25 chars)

space, \t, ", ', &, |, ;, <, >, (, ), ^, %, !, $, `, *, ?, [, ], {, }, ~, \n, \r

Identical to the former IsShellMetachar switch — no behavioral change.

Trade-offs

  • SearchValues<char> requires System.Buffers (using added) — available since .NET 8; this project targets net10.0.
  • The static field is initialized once; subsequent calls pay only the span scan cost.
  • No change to QuoteForShell or FormatExecCommand — only the metachar detection inner loop is affected.

Test Status

All existing ShellQuotingTests pass unchanged (covering all 25 metacharacters, empty/plain args, QuoteForShell cmd and PowerShell paths, FormatExecCommand edge cases).

Shared.Tests: 586 passed, 20 skipped — exit 0
Tray.Tests: 122 passed — exit 0

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

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@97143ac59cb3a13ef2a77581f929f06719c7402a

… scan

Replace per-character foreach+switch with System.Buffers.SearchValues<char>,
which uses SSE2/AVX2 vectorized IndexOfAny to detect shell metacharacters
in a single SIMD pass instead of a character-by-character loop.

- Add static SearchValues<char> s_shellMetachars (same 25-char set as former
- Replace NeedsQuoting foreach body with arg.AsSpan().IndexOfAny(s_shellMetachars) >= 0
- Remove private IsShellMetachar helper (no longer needed)
- Add using System.Buffers (SearchValues<T> namespace)

SearchValues<char> is available since .NET 8; this project targets net10.0.
All existing ShellQuotingTests pass unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@shanselman shanselman marked this pull request as ready for review April 20, 2026 05:36
@shanselman shanselman merged commit e9f18f7 into master Apr 20, 2026
@shanselman shanselman deleted the repo-assist/improve-shellquoting-search-values-2026-04-19-6661ff63fb4feb01 branch April 20, 2026 05:36
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.

1 participant