Skip to content

Commit 0b93d43

Browse files
trevnorrisMichael Scovetta
authored and
Michael Scovetta
committed
node: improve accessor perf of process.env
Set process.env array entries in JS. PR-URL: nodejs#3780 Reviewed-By: Fedor Indutny <[email protected]>
1 parent 8800d76 commit 0b93d43

File tree

2 files changed

+48
-13
lines changed

2 files changed

+48
-13
lines changed

benchmark/misc/bench-env.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
const bench = common.createBenchmark(main, {
6+
n: [1e5],
7+
});
8+
9+
10+
function main(conf) {
11+
const n = conf.n >>> 0;
12+
bench.start();
13+
for (var i = 0; i < n; i++) {
14+
// Access every item in object to process values.
15+
Object.keys(process.env);
16+
}
17+
bench.end(n);
18+
}

src/node.cc

+30-13
Original file line numberDiff line numberDiff line change
@@ -2560,31 +2560,42 @@ static void EnvDeleter(Local<String> property,
25602560

25612561

25622562
static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2563-
Isolate* isolate = info.GetIsolate();
2563+
Environment* env = Environment::GetCurrent(info);
2564+
Isolate* isolate = env->isolate();
2565+
Local<Context> ctx = env->context();
2566+
Local<Function> fn = env->push_values_to_array_function();
2567+
Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
2568+
size_t idx = 0;
2569+
25642570
#ifdef __POSIX__
25652571
int size = 0;
25662572
while (environ[size])
25672573
size++;
25682574

2569-
Local<Array> envarr = Array::New(isolate, size);
2575+
Local<Array> envarr = Array::New(isolate);
25702576

25712577
for (int i = 0; i < size; ++i) {
25722578
const char* var = environ[i];
25732579
const char* s = strchr(var, '=');
25742580
const int length = s ? s - var : strlen(var);
2575-
Local<String> name = String::NewFromUtf8(isolate,
2576-
var,
2577-
String::kNormalString,
2578-
length);
2579-
envarr->Set(i, name);
2581+
argv[idx] = String::NewFromUtf8(isolate,
2582+
var,
2583+
String::kNormalString,
2584+
length);
2585+
if (++idx >= ARRAY_SIZE(argv)) {
2586+
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2587+
idx = 0;
2588+
}
2589+
}
2590+
if (idx > 0) {
2591+
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
25802592
}
25812593
#else // _WIN32
25822594
WCHAR* environment = GetEnvironmentStringsW();
25832595
if (environment == nullptr)
25842596
return; // This should not happen.
25852597
Local<Array> envarr = Array::New(isolate);
25862598
WCHAR* p = environment;
2587-
int i = 0;
25882599
while (*p) {
25892600
WCHAR *s;
25902601
if (*p == L'=') {
@@ -2599,13 +2610,19 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
25992610
}
26002611
const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
26012612
const size_t two_byte_buffer_len = s - p;
2602-
Local<String> value = String::NewFromTwoByte(isolate,
2603-
two_byte_buffer,
2604-
String::kNormalString,
2605-
two_byte_buffer_len);
2606-
envarr->Set(i++, value);
2613+
argv[idx] = String::NewFromTwoByte(isolate,
2614+
two_byte_buffer,
2615+
String::kNormalString,
2616+
two_byte_buffer_len);
2617+
if (++idx >= ARRAY_SIZE(argv)) {
2618+
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2619+
idx = 0;
2620+
}
26072621
p = s + wcslen(s) + 1;
26082622
}
2623+
if (idx > 0) {
2624+
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2625+
}
26092626
FreeEnvironmentStringsW(environment);
26102627
#endif
26112628

0 commit comments

Comments
 (0)