From d8c527f24f695c54722ac524a1e868a3bedad33a Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 8 Feb 2023 10:58:44 +0100 Subject: [PATCH] http: use v8::Array::New() with a prebuilt vector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid using v8::Array::Set() which results in JS execution and is thus slow. Prebuild the vector in C++ land and build the JS array directly with that vector whereever possible. PR-URL: https://github.com/nodejs/node/pull/46447 Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: Robert Nagy Reviewed-By: Darshan Sen Reviewed-By: Gerhard Stöbich Reviewed-By: James M Snell --- src/node_http_parser.cc | 51 ++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 1bfa8e0faf23cf..bb2019c7445785 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -1037,68 +1037,60 @@ void ConnectionsList::New(const FunctionCallbackInfo& args) { void ConnectionsList::All(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - Local context = isolate->GetCurrentContext(); - Local all = Array::New(isolate); ConnectionsList* list; ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder()); - uint32_t i = 0; + std::vector> result; + result.reserve(list->all_connections_.size()); for (auto parser : list->all_connections_) { - if (all->Set(context, i++, parser->object()).IsNothing()) { - return; - } + result.emplace_back(parser->object()); } - return args.GetReturnValue().Set(all); + return args.GetReturnValue().Set( + Array::New(isolate, result.data(), result.size())); } void ConnectionsList::Idle(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - Local context = isolate->GetCurrentContext(); - Local idle = Array::New(isolate); ConnectionsList* list; ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder()); - uint32_t i = 0; + std::vector> result; + result.reserve(list->all_connections_.size()); for (auto parser : list->all_connections_) { if (parser->last_message_start_ == 0) { - if (idle->Set(context, i++, parser->object()).IsNothing()) { - return; - } + result.emplace_back(parser->object()); } } - return args.GetReturnValue().Set(idle); + return args.GetReturnValue().Set( + Array::New(isolate, result.data(), result.size())); } void ConnectionsList::Active(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - Local context = isolate->GetCurrentContext(); - Local active = Array::New(isolate); ConnectionsList* list; ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder()); - uint32_t i = 0; + std::vector> result; + result.reserve(list->active_connections_.size()); for (auto parser : list->active_connections_) { - if (active->Set(context, i++, parser->object()).IsNothing()) { - return; - } + result.emplace_back(parser->object()); } - return args.GetReturnValue().Set(active); + return args.GetReturnValue().Set( + Array::New(isolate, result.data(), result.size())); } void ConnectionsList::Expired(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - Local context = isolate->GetCurrentContext(); - Local expired = Array::New(isolate); ConnectionsList* list; ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder()); @@ -1110,7 +1102,7 @@ void ConnectionsList::Expired(const FunctionCallbackInfo& args) { static_cast(args[1].As()->Value()) * 1000000; if (headers_timeout == 0 && request_timeout == 0) { - return args.GetReturnValue().Set(expired); + return args.GetReturnValue().Set(Array::New(isolate, 0)); } else if (request_timeout > 0 && headers_timeout > request_timeout) { std::swap(headers_timeout, request_timeout); } @@ -1121,9 +1113,11 @@ void ConnectionsList::Expired(const FunctionCallbackInfo& args) { const uint64_t request_deadline = request_timeout > 0 ? now - request_timeout : 0; - uint32_t i = 0; auto iter = list->active_connections_.begin(); auto end = list->active_connections_.end(); + + std::vector> result; + result.reserve(list->active_connections_.size()); while (iter != end) { Parser* parser = *iter; iter++; @@ -1136,15 +1130,14 @@ void ConnectionsList::Expired(const FunctionCallbackInfo& args) { request_deadline > 0 && parser->last_message_start_ < request_deadline) ) { - if (expired->Set(context, i++, parser->object()).IsNothing()) { - return; - } + result.emplace_back(parser->object()); list->active_connections_.erase(parser); } } - return args.GetReturnValue().Set(expired); + return args.GetReturnValue().Set( + Array::New(isolate, result.data(), result.size())); } const llhttp_settings_t Parser::settings = {