mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
src: use ObjectTemplate for creating stream req objs
This allows V8 to avoid preparing a execution context
for the constructor, to give a (kinda) small but noticeable
perf gain.
Benchmarks (only this commit):
$ ./node benchmark/compare.js --new ./node --old ./node-master --filter net-c2s.js --set len=10 --set type=asc --runs 360 net | Rscript benchmark/compare.R
[01:15:27|% 100| 1/1 files | 720/720 runs | 1/1 configs]: Done
confidence improvement accuracy (*) (**) (***)
net/net-c2s.js dur=5 type='asc' len=10 *** 0.69 % ±0.31% ±0.41% ±0.53%
PR-URL: https://github.com/nodejs/node/pull/18936
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
4 files changed
+25
-9
No files matched your search
@@ -329,7 +329,7 @@ struct PackageConfig {
|
||||
V(script_context_constructor_template, v8::FunctionTemplate) \
|
||||
V(script_data_constructor_function, v8::Function) \
|
||||
V(secure_context_constructor_template, v8::FunctionTemplate) \
|
||||
V(shutdown_wrap_constructor_function, v8::Function) \
|
||||
V(shutdown_wrap_template, v8::ObjectTemplate) \
|
||||
V(tcp_constructor_template, v8::FunctionTemplate) \
|
||||
V(tick_callback_function, v8::Function) \
|
||||
V(timers_callback_function, v8::Function) \
|
||||
@@ -338,7 +338,7 @@ struct PackageConfig {
|
||||
V(udp_constructor_function, v8::Function) \
|
||||
V(vm_parsing_context_symbol, v8::Symbol) \
|
||||
V(url_constructor_function, v8::Function) \
|
||||
V(write_wrap_constructor_function, v8::Function) \
|
||||
V(write_wrap_template, v8::ObjectTemplate) \
|
||||
V(fs_use_promises_symbol, v8::Symbol)
|
||||
|
||||
class Environment;
|
||||
|
||||
+13
-2
@@ -164,8 +164,9 @@ inline int StreamBase::Shutdown(v8::Local<v8::Object> req_wrap_obj) {
|
||||
|
||||
if (req_wrap_obj.IsEmpty()) {
|
||||
req_wrap_obj =
|
||||
env->shutdown_wrap_constructor_function()
|
||||
env->shutdown_wrap_template()
|
||||
->NewInstance(env->context()).ToLocalChecked();
|
||||
StreamReq::ResetObject(req_wrap_obj);
|
||||
}
|
||||
|
||||
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
|
||||
@@ -203,8 +204,9 @@ inline StreamWriteResult StreamBase::Write(
|
||||
|
||||
if (req_wrap_obj.IsEmpty()) {
|
||||
req_wrap_obj =
|
||||
env->write_wrap_constructor_function()
|
||||
env->write_wrap_template()
|
||||
->NewInstance(env->context()).ToLocalChecked();
|
||||
StreamReq::ResetObject(req_wrap_obj);
|
||||
}
|
||||
|
||||
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
|
||||
@@ -427,6 +429,15 @@ inline void StreamReq::Done(int status, const char* error_str) {
|
||||
OnDone(status);
|
||||
}
|
||||
|
||||
inline void StreamReq::ResetObject(v8::Local<v8::Object> obj) {
|
||||
#ifdef DEBUG
|
||||
CHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField);
|
||||
#endif
|
||||
ClearWrap(obj);
|
||||
obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr);
|
||||
}
|
||||
|
||||
|
||||
} // namespace node
|
||||
|
||||
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
@@ -46,6 +46,13 @@ class StreamReq {
|
||||
|
||||
static StreamReq* FromObject(v8::Local<v8::Object> req_wrap_obj);
|
||||
|
||||
// Sets all internal fields of `req_wrap_obj` to `nullptr`.
|
||||
// This is what the `WriteWrap` and `ShutdownWrap` JS constructors do,
|
||||
// and what we use in C++ after creating these objects from their
|
||||
// v8::ObjectTemplates, to avoid the overhead of calling the
|
||||
// constructor explicitly.
|
||||
static inline void ResetObject(v8::Local<v8::Object> req_wrap_obj);
|
||||
|
||||
protected:
|
||||
virtual void OnDone(int status) = 0;
|
||||
|
||||
|
||||
+3
-5
@@ -60,9 +60,7 @@ void LibuvStreamWrap::Initialize(Local<Object> target,
|
||||
auto is_construct_call_callback =
|
||||
[](const FunctionCallbackInfo<Value>& args) {
|
||||
CHECK(args.IsConstructCall());
|
||||
ClearWrap(args.This());
|
||||
args.This()->SetAlignedPointerInInternalField(
|
||||
StreamReq::kStreamReqField, nullptr);
|
||||
StreamReq::ResetObject(args.This());
|
||||
};
|
||||
Local<FunctionTemplate> sw =
|
||||
FunctionTemplate::New(env->isolate(), is_construct_call_callback);
|
||||
@@ -72,7 +70,7 @@ void LibuvStreamWrap::Initialize(Local<Object> target,
|
||||
sw->SetClassName(wrapString);
|
||||
AsyncWrap::AddWrapMethods(env, sw);
|
||||
target->Set(wrapString, sw->GetFunction());
|
||||
env->set_shutdown_wrap_constructor_function(sw->GetFunction());
|
||||
env->set_shutdown_wrap_template(sw->InstanceTemplate());
|
||||
|
||||
Local<FunctionTemplate> ww =
|
||||
FunctionTemplate::New(env->isolate(), is_construct_call_callback);
|
||||
@@ -82,7 +80,7 @@ void LibuvStreamWrap::Initialize(Local<Object> target,
|
||||
ww->SetClassName(writeWrapString);
|
||||
AsyncWrap::AddWrapMethods(env, ww);
|
||||
target->Set(writeWrapString, ww->GetFunction());
|
||||
env->set_write_wrap_constructor_function(ww->GetFunction());
|
||||
env->set_write_wrap_template(ww->InstanceTemplate());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user