http: optimize corked writes and header pair tracking
This PR contains two focused HTTP performance improvements without adding or
changing public APIs.
Optimize corked outgoing writes
OutgoingMessage.uncork() previously uncorked the underlying socket before
flushing its buffered HTTP chunk. The individual framing writes therefore
bypassed socket-level batching.
Buffered body data could also be flushed after the terminating chunk when
end() was called while the message was still corked.
This change:
- flushes buffered HTTP chunks before uncorking the socket;
- flushes buffered body data before writing the terminating chunk;
- preserves callback ordering, backpressure, trailers, TLS, and pipelining;
- prevents a synchronous
drainlistener from writing after the terminating
chunk.
Cache maxHeaderPairs
The HTTP parser previously read the JavaScript maxHeaderPairs property for
every header field.
This change caches the value once per independent header section and
invalidates it for:
- trailers;
- the next pipelined message;
- parser reinitialization.
The parser benchmark now explicitly uses the production default of 2000 header
pairs because direct benchmark parsers bypass cleanParser().
Performance
Local macOS arm64 Release results, using the median of three short runs:
| Scenario | Before | After | Improvement |
|---|---|---|---|
| Core HTTP corked writes | 17.3k req/s | 59.5k req/s | 3.44x |
| Express corked writes | 16.6k req/s | 50.8k req/s | 3.06x |
Parser benchmark improvements:
| Header fields | Improvement |
|---|---|
| 5 | 22% |
| 17 | 54% |
End-to-end HTTP header benchmarks improved by approximately 4.8% to 7.1%.
Tests
- Release build completed successfully.
- ESLint, cpplint, checkimports, and
git diff --checkpassed. - The focused HTTP test set passed across 80 repeated executions.
- All existing
test-http-parser-*tests passed. - All existing
test-http-outgoing-*tests passed. - Additional HTTP chunking, trailer, and pipelining tests passed.
- The new tests cover HTTP and HTTPS, client and server messages, nested
corking, callback ordering, trailers, backpressure, and queued pipelined
responses.
Documentation was not changed because no public API or documented behavior is
introduced.