Skip to content

Commit 72448a8

Browse files
mcollinaaduh95
authored andcommitted
http2: avoid copying the options in respond()
respond() copied the user-provided options object on every call just so it could normalize and locally flip options.endStream, and prepareResponseHeadersObject() then looked the :status and date fields up again on the dictionary-mode null-prototype headers copy it had just built. Use a local variable for endStream and pick up :status/date while copying the headers instead. No measurable throughput change on its own; this removes an object clone and several dictionary-mode property lookups per response. Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: #64265 Backport-PR-URL: #64663 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Tim Perry <pimterry@gmail.com> Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
1 parent f6692da commit 72448a8

1 file changed

Lines changed: 20 additions & 15 deletions

File tree

‎lib/internal/http2/core.js‎

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,31 +2654,35 @@ function prepareResponseHeaders(stream, headersParam, options) {
26542654
functionprepareResponseHeadersObject(oldHeaders,options){
26552655
assertIsObject(oldHeaders,'headers',['Object','Array']);
26562656
constheaders={__proto__: null};
2657+
letstatusCode;
2658+
lethasDate=false;
26572659

26582660
if(oldHeaders!==null&&oldHeaders!==undefined){
26592661
// This loop is here for performance reason. Do not change.
2662+
// The :status and date fields are picked up while copying so they do
2663+
// not have to be looked up again on the null-prototype copy.
26602664
for(constkeyinoldHeaders){
26612665
if(ObjectHasOwn(oldHeaders,key)){
2662-
headers[key]=oldHeaders[key];
2666+
constvalue=oldHeaders[key];
2667+
headers[key]=value;
2668+
if(key===HTTP2_HEADER_STATUS)
2669+
statusCode=value;
2670+
elseif(key===HTTP2_HEADER_DATE)
2671+
hasDate=value!=null;
26632672
}
26642673
}
26652674
headers[kSensitiveHeaders]=oldHeaders[kSensitiveHeaders];
26662675
}
26672676

2668-
conststatusCode=
2669-
headers[HTTP2_HEADER_STATUS]=
2670-
headers[HTTP2_HEADER_STATUS]|0||HTTP_STATUS_OK;
2677+
statusCode=headers[HTTP2_HEADER_STATUS]=statusCode|0||HTTP_STATUS_OK;
26712678

2672-
if(options.sendDate==null||options.sendDate){
2673-
headers[HTTP2_HEADER_DATE]??=utcDate();
2679+
if(!hasDate&&(options.sendDate==null||options.sendDate)){
2680+
headers[HTTP2_HEADER_DATE]=utcDate();
26742681
}
26752682

26762683
validatePreparedResponseHeaders(headers,statusCode);
26772684

2678-
return{
2679-
headers,
2680-
statusCode: headers[HTTP2_HEADER_STATUS],
2681-
};
2685+
return{ headers, statusCode };
26822686
}
26832687

26842688
functionprepareResponseHeadersArray(headers,options){
@@ -3047,15 +3051,17 @@ class ServerHttp2Stream extends Http2Stream {
30473051
conststate=this[kState];
30483052

30493053
assertIsObject(options,'options');
3050-
options={ ...options};
3054+
// The options are only read, never mutated, so the user-provided object
3055+
// can be used directly instead of copying it.
3056+
options??=kEmptyObject;
30513057

30523058
debugStreamObj(this,'initiating response');
30533059
this[kUpdateTimer]();
30543060

3055-
options.endStream=!!options.endStream;
3061+
constendStream=!!options.endStream;
30563062

30573063
letstreamOptions=0;
3058-
if(options.endStream)
3064+
if(endStream)
30593065
streamOptions|=STREAM_OPTION_EMPTY_PAYLOAD;
30603066

30613067
if(options.waitForTrailers){
@@ -3073,12 +3079,11 @@ class ServerHttp2Stream extends Http2Stream {
30733079

30743080
// Close the writable side if the endStream option is set or status
30753081
// is one of known codes with no payload, or it's a head request
3076-
if(!!options.endStream||
3082+
if(endStream||
30773083
statusCode===HTTP_STATUS_NO_CONTENT||
30783084
statusCode===HTTP_STATUS_RESET_CONTENT||
30793085
statusCode===HTTP_STATUS_NOT_MODIFIED||
30803086
this.headRequest===true){
3081-
options.endStream=true;
30823087
this.end();
30833088
}
30843089

0 commit comments

Comments
 (0)