Browse Source

node: improve accessor perf of process.env

Set process.env array entries in JS.

PR-URL: https://github.com/nodejs/node/pull/3780
Reviewed-By: Fedor Indutny <fedor@indutny.com>
v5.x
Trevor Norris 9 years ago
committed by Jeremiah Senkpiel
parent
commit
ecef817a28
  1. 18
      benchmark/misc/bench-env.js
  2. 43
      src/node.cc

18
benchmark/misc/bench-env.js

@ -0,0 +1,18 @@
'use strict';
const common = require('../common');
const bench = common.createBenchmark(main, {
n: [1e5],
});
function main(conf) {
const n = conf.n >>> 0;
bench.start();
for (var i = 0; i < n; i++) {
// Access every item in object to process values.
Object.keys(process.env);
}
bench.end(n);
}

43
src/node.cc

@ -2560,23 +2560,35 @@ static void EnvDeleter(Local<String> property,
static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) { static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
Isolate* isolate = info.GetIsolate(); Environment* env = Environment::GetCurrent(info);
Isolate* isolate = env->isolate();
Local<Context> ctx = env->context();
Local<Function> fn = env->push_values_to_array_function();
Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
size_t idx = 0;
#ifdef __POSIX__ #ifdef __POSIX__
int size = 0; int size = 0;
while (environ[size]) while (environ[size])
size++; size++;
Local<Array> envarr = Array::New(isolate, size); Local<Array> envarr = Array::New(isolate);
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
const char* var = environ[i]; const char* var = environ[i];
const char* s = strchr(var, '='); const char* s = strchr(var, '=');
const int length = s ? s - var : strlen(var); const int length = s ? s - var : strlen(var);
Local<String> name = String::NewFromUtf8(isolate, argv[idx] = String::NewFromUtf8(isolate,
var, var,
String::kNormalString, String::kNormalString,
length); length);
envarr->Set(i, name); if (++idx >= ARRAY_SIZE(argv)) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
idx = 0;
}
}
if (idx > 0) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
} }
#else // _WIN32 #else // _WIN32
WCHAR* environment = GetEnvironmentStringsW(); WCHAR* environment = GetEnvironmentStringsW();
@ -2584,7 +2596,6 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
return; // This should not happen. return; // This should not happen.
Local<Array> envarr = Array::New(isolate); Local<Array> envarr = Array::New(isolate);
WCHAR* p = environment; WCHAR* p = environment;
int i = 0;
while (*p) { while (*p) {
WCHAR *s; WCHAR *s;
if (*p == L'=') { if (*p == L'=') {
@ -2599,13 +2610,19 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
} }
const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p); const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
const size_t two_byte_buffer_len = s - p; const size_t two_byte_buffer_len = s - p;
Local<String> value = String::NewFromTwoByte(isolate, argv[idx] = String::NewFromTwoByte(isolate,
two_byte_buffer, two_byte_buffer,
String::kNormalString, String::kNormalString,
two_byte_buffer_len); two_byte_buffer_len);
envarr->Set(i++, value); if (++idx >= ARRAY_SIZE(argv)) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
idx = 0;
}
p = s + wcslen(s) + 1; p = s + wcslen(s) + 1;
} }
if (idx > 0) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
}
FreeEnvironmentStringsW(environment); FreeEnvironmentStringsW(environment);
#endif #endif

Loading…
Cancel
Save