C++23 memory and performance optimization

  • cplusplus
  • cplusplus23
  • performance
  • memory
  • http
  • parser
  • benchmark
  • english

posted on 28 Jul 2026 under category programming

Post Meta-Data

Date Language Author Description
28.07.2026 English Claus Prüfer (Chief Prüfer) C++23 Parser Optimization: string_view And Spanstream Reduce Time And Memory

C++23 Memory And Performance Optimization In HTTP/1.2 Parser Code

EmojiMicroscopeEmojiMicroscopeEmojiMicroscope

This article documents the technical changes and benchmark impact of WEBcodeX1/http-1.2 PR #2031.
The PR modernizes the HTTP parser from a C++11-style, allocation-heavy implementation to a C++23-oriented approach with std::string_view, std::span, and std::ispanstream.

The key result is simple: the parser performs less heap work, copies less data, and therefore runs faster while consuming significantly less memory.

Key Concepts

std::string_view

std::string_view is a non-owning view over existing character buffers.
Instead of creating new std::string objects for every substring operation, parsing logic can reference slices of already available memory.

For parser workloads this is highly relevant because tokenization often creates many short-lived substrings. Eliminating those copies directly reduces allocation pressure.

std::span And std::ispanstream (C++23)

The optimized header parser reads request data through:

  • std::span<const char> as a safe view over contiguous request bytes
  • std::ispanstream for line-by-line stream parsing without building intermediate copied buffers

This replaces the old split-based approach that built vectors of temporary strings and modified request data in place.

Transparent unordered_map Hashing

The PR introduces a transparent hash (StringHash with is_transparent) and equal_to<> in map types.
This allows heterogeneous lookups (for example string-literals / views) without constructing temporary std::string keys.

That reduces hidden allocations during map access paths.

Non-Destructive Split Overload

A new split overload accepts string_view and returns vector<string_view>.
Compared to destructive split on mutable strings, this avoids repeated erase/copy behavior during tokenization and keeps input buffers unchanged where mutation is unnecessary.

API And Data-Flow Improvements

  • getRequests() now returns const RequestsMap_t& instead of returning by value
  • Prefix removal changed from replace(0, n, "") to erase(0, n)
  • Internal parse methods now accept string_view where possible

These changes remove avoidable data movement and avoid full container copies.

Old Code VS. New Code

Header Parsing Path

Old Behavior (Legacy/C++11)

The old implementation:

  1. Copied input into mutable strings
  2. Split headers into vector<string>
  3. Reverse-split each line into another temporary vector
  4. Inserted parsed values into maps

This generated many temporary allocations and frequent short-lived objects.

New Behavior (C++23)

The new implementation:

  1. Streams over request memory using std::ispanstream
  2. Processes one line at a time with minimal intermediate objects
  3. Uses string_view slices for key/value extraction
  4. Materializes std::string mainly at final map insertion boundaries

Result: less heap churn and lower parser overhead.

GET Parameter Parsing Path

Old Behavior

  • Creates copied parameter substrings via substr
  • Destructive split into owned vector<string>
  • Additional substring copies for key/value

New Behavior

  • Keeps URL parameters as string_view
  • Splits into vector<string_view>
  • Converts to owned strings only when final map storage is required

Result: fewer transient strings and lower allocator activity.

Execution Time

The benchmark1 generated 500 random valid HTTP requests with varying header counts, GET parameter counts, payload sizes, and mixed GET/POST patterns. Each request was repeatedly measured and results exported to CSV.

Performance Summary

  • Header parsing
    • New: 449 µs total
    • Legacy: 1376 µs total
    • Speedup: 3.06x
  • GET parameter parsing
    • New: 54 µs total
    • Legacy: 68 µs total
    • Speedup: 1.24x

Technical Reason

Execution time improves mainly because:

  1. fewer allocations reduce allocator overhead,
  2. fewer copies reduce memory bandwidth pressure,
  3. less mutation of intermediate buffers reduces unnecessary operations,
  4. simplified parse flow improves cache locality and branch behavior.

Header parsing benefits most because the old flow had the highest temporary-object density.

Memory Consumption

The memory benchmark tracked allocation calls and total allocated bytes using global operator new wrappers, across 500 requests with median aggregation over repeated measurements.

Memory Summary

  • Header parsing allocated bytes
    • New: 503,661
    • Legacy: 1,813,194
    • Reduction: 72.2%
  • GET parameter parsing allocated bytes
    • New: 89,832
    • Legacy: 122,038
    • Reduction: 26.4%

Technical Reason

Memory consumption is lower because string_view and streaming parsing replace copy-heavy token pipelines.
The old code allocated aggressively for intermediate split containers and substrings.
The new code mostly allocates where ownership is genuinely required (final map storage), not during each parse step.

Conclusion

PR #2031 is a textbook example of modern C++ parser optimization: migrate from copy-centric string handling to view-centric parsing with controlled ownership boundaries.

The benchmark data confirms that this is not merely stylistic modernization:

  • significantly faster execution, especially in header parsing,
  • sharply reduced allocation volume,
  • cleaner internal APIs with less accidental copying.

For protocol-heavy systems, these improvements scale directly with request volume and are therefore highly relevant for real production workloads.


  1. WEBcodeX1/http-1.2 Pull Request #203 — perf: optimize httpparser with C++23 string_view, ispanstream, and transparent maps: https://github.com/WEBcodeX1/http-1.2/pull/203  2 3