Skip to content

Optimize sanitizer hot paths for high-throughput response conversion #3117

Description

@SamMorrowDrums

Describe the bug

Sanitization is now applied consistently across user-authored response fields, but the current pipeline performs repeated rune conversion and multiple full-string passes. At high request rates this becomes allocation- and GC-bound on list/comment-heavy responses.

Measured examples on current main:

  • 100 comments × 1 KiB: about 3.35 ms and 2.06 MiB allocated per conversion.
  • 30 issues with 2 KiB bodies: about 2.14 ms and 1.30 MiB allocated.
  • A 64 KiB body: about 2.38 ms and 1.21 MiB allocated.

At roughly 1,250 requests/second, workloads dominated by these shapes can require several CPU cores and produce multi-gigabyte/second allocation rates.

Affected version

Current main as of 2026-08-19, after the sanitizer coverage and post-normalization Unicode filtering changes.

Steps to reproduce the behavior

  1. Benchmark sanitize.Sanitize for short titles, 1 KiB comments, and 64 KiB bodies.
  2. Benchmark representative minimal-converter pages containing 30 issues or 100 comments.
  3. Compare CPU time and allocations with the pre-sanitization converter paths.
  4. Observe repeated []rune conversion and post-normalization passes dominating CPU and allocations.

Expected vs actual behavior

Expected: sanitization preserves the current output and security policy with negligible overhead for ordinary clean text.

Actual: benign content pays for repeated allocating scans and HTML-policy processing, making high-throughput response conversion GC-bound.

Optimize without weakening behavior:

  • Make invisible-character filtering scan first and return the original string without allocation when no filtered rune exists.
  • Skip the post-HTML invisible/code-fence pass when normalization returned unchanged content.
  • Add only a conservative, proven-safe fast path for clean printable ASCII that cannot contain HTML/entity syntax.
  • Preserve byte-for-byte sanitizer output across a broad corpus, fuzz/property tests, and all existing edge cases.
  • Add committed benchmarks and report before/after CPU and allocation results for representative response shapes.

Logs

N/A

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions