mirror of
https://github.com/nodejs/node.git
synced 2025-05-17 22:02:33 +00:00
node: improve GetActiveRequests performance
v8 is faster at setting object properties in JS than C++. Even when it requires calling into JS from native code. Make process._getActiveRequests() faster by doing this when populating the array containing request objects. Simple benchmark: for (let i = 0; i < 22; i++) fs.open(__filename, 'r', function() { }); let t = process.hrtime(); for (let i = 0; i < 1e6; i++) process._getActiveRequests(); t = process.hrtime(t); console.log((t[0] * 1e9 + t[1]) / 1e6); Results between the two: Previous: 4406 ns/op Patched: 690 ns/op 5.4x faster PR-URL: https://github.com/nodejs/node/pull/3375 Reviewed-By: James Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <ben@strongloop.com>
This commit is contained in:
parent
b354be7761
commit
494227bb03
@ -227,6 +227,7 @@ namespace node {
|
||||
V(zero_return_string, "ZERO_RETURN") \
|
||||
|
||||
#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \
|
||||
V(add_properties_by_index_function, v8::Function) \
|
||||
V(as_external, v8::External) \
|
||||
V(async_hooks_init_function, v8::Function) \
|
||||
V(async_hooks_pre_function, v8::Function) \
|
||||
|
39
src/node.cc
39
src/node.cc
@ -1009,6 +1009,17 @@ void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
|
||||
void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
CHECK(args[0]->IsFunction());
|
||||
|
||||
env->set_add_properties_by_index_function(args[0].As<Function>());
|
||||
env->process_object()->Delete(
|
||||
FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject"));
|
||||
}
|
||||
|
||||
|
||||
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
@ -1546,11 +1557,30 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
Local<Array> ary = Array::New(args.GetIsolate());
|
||||
int i = 0;
|
||||
Local<Context> ctx = env->context();
|
||||
Local<Function> fn = env->add_properties_by_index_function();
|
||||
static const size_t argc = 8;
|
||||
Local<Value> argv[argc];
|
||||
size_t i = 0;
|
||||
|
||||
for (auto w : *env->req_wrap_queue())
|
||||
if (w->persistent().IsEmpty() == false)
|
||||
ary->Set(i++, w->object());
|
||||
for (auto w : *env->req_wrap_queue()) {
|
||||
if (w->persistent().IsEmpty() == false) {
|
||||
argv[i++ % argc] = w->object();
|
||||
if ((i % argc) == 0) {
|
||||
HandleScope scope(env->isolate());
|
||||
fn->Call(ctx, ary, argc, argv).ToLocalChecked();
|
||||
for (auto&& arg : argv) {
|
||||
arg = Local<Value>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const size_t remainder = i % argc;
|
||||
if (remainder > 0) {
|
||||
HandleScope scope(env->isolate());
|
||||
fn->Call(ctx, ary, remainder, argv).ToLocalChecked();
|
||||
}
|
||||
|
||||
args.GetReturnValue().Set(ary);
|
||||
}
|
||||
@ -2979,6 +3009,7 @@ void SetupProcessObject(Environment* env,
|
||||
env->SetMethod(process, "binding", Binding);
|
||||
env->SetMethod(process, "_linkedBinding", LinkedBinding);
|
||||
|
||||
env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
|
||||
env->SetMethod(process, "_setupNextTick", SetupNextTick);
|
||||
env->SetMethod(process, "_setupPromises", SetupPromises);
|
||||
env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
|
||||
|
11
src/node.js
11
src/node.js
@ -22,6 +22,8 @@
|
||||
|
||||
process.EventEmitter = EventEmitter; // process.EventEmitter is deprecated
|
||||
|
||||
startup.setupProcessObject();
|
||||
|
||||
// do this good and early, since it handles errors.
|
||||
startup.processFatal();
|
||||
|
||||
@ -173,6 +175,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
startup.setupProcessObject = function() {
|
||||
process._setupProcessObject(setPropByIndex);
|
||||
|
||||
function setPropByIndex() {
|
||||
for (var i = 0; i < arguments.length; i++)
|
||||
this.push(arguments[i]);
|
||||
}
|
||||
};
|
||||
|
||||
startup.globalVariables = function() {
|
||||
global.process = process;
|
||||
global.global = global;
|
||||
|
10
test/parallel/test-process-getactiverequests.js
Normal file
10
test/parallel/test-process-getactiverequests.js
Normal file
@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
|
||||
for (let i = 0; i < 12; i++)
|
||||
fs.open(__filename, 'r', function() { });
|
||||
|
||||
assert.equal(12, process._getActiveRequests().length);
|
Loading…
Reference in New Issue
Block a user