diff --git a/benchmark/fs/bench-readdir.js b/benchmark/fs/bench-readdir.js
new file mode 100644
index 00000000000000..2f0eab6a821f42
--- /dev/null
+++ b/benchmark/fs/bench-readdir.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const common = require('../common');
+const fs = require('fs');
+
+const bench = common.createBenchmark(main, {
+  n: [1e4],
+});
+
+
+function main(conf) {
+  const n = conf.n >>> 0;
+
+  bench.start();
+  (function r(cntr) {
+    if (--cntr <= 0)
+      return bench.end(n);
+    fs.readdir(__dirname + '/../../lib/', function() {
+      r(cntr);
+    });
+  }(n));
+}
diff --git a/benchmark/fs/bench-readdirSync.js b/benchmark/fs/bench-readdirSync.js
new file mode 100644
index 00000000000000..9f89649138cd20
--- /dev/null
+++ b/benchmark/fs/bench-readdirSync.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const common = require('../common');
+const fs = require('fs');
+
+const bench = common.createBenchmark(main, {
+  n: [1e4],
+});
+
+
+function main(conf) {
+  const n = conf.n >>> 0;
+
+  bench.start();
+  for (var i = 0; i < n; i++) {
+    fs.readdirSync(__dirname + '/../../lib/');
+  }
+  bench.end(n);
+}
diff --git a/benchmark/http/bench-parser.js b/benchmark/http/bench-parser.js
new file mode 100644
index 00000000000000..989d9a994fa04e
--- /dev/null
+++ b/benchmark/http/bench-parser.js
@@ -0,0 +1,55 @@
+'use strict';
+
+const common = require('../common');
+const HTTPParser = process.binding('http_parser').HTTPParser;
+const REQUEST = HTTPParser.REQUEST;
+const kOnHeaders = HTTPParser.kOnHeaders | 0;
+const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
+const kOnBody = HTTPParser.kOnBody | 0;
+const kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
+const CRLF = '\r\n';
+
+const bench = common.createBenchmark(main, {
+  fields: [4, 8, 16, 32],
+  n: [1e5],
+});
+
+
+function main(conf) {
+  const fields = conf.fields >>> 0;
+  const n = conf.n >>> 0;
+  var header = `GET /hello HTTP/1.1${CRLF}Content-Type: text/plain${CRLF}`;
+
+  for (var i = 0; i < fields; i++) {
+    header += `X-Filler${i}: ${Math.random().toString(36).substr(2)}${CRLF}`;
+  }
+  header += CRLF;
+
+  processHeader(new Buffer(header), n);
+}
+
+
+function processHeader(header, n) {
+  const parser = newParser(REQUEST);
+
+  bench.start();
+  for (var i = 0; i < n; i++) {
+    parser.execute(header, 0, header.length);
+    parser.reinitialize(REQUEST);
+  }
+  bench.end(n);
+}
+
+
+function newParser(type) {
+  const parser = new HTTPParser(type);
+
+  parser.headers = [];
+
+  parser[kOnHeaders] = function() { };
+  parser[kOnHeadersComplete] = function() { };
+  parser[kOnBody] = function() { };
+  parser[kOnMessageComplete] = function() { };
+
+  return parser;
+}
diff --git a/benchmark/misc/bench-env.js b/benchmark/misc/bench-env.js
new file mode 100644
index 00000000000000..66f966f587bb7f
--- /dev/null
+++ b/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);
+}
diff --git a/benchmark/misc/bench-hrtime.js b/benchmark/misc/bench-hrtime.js
new file mode 100644
index 00000000000000..661dff43b0103c
--- /dev/null
+++ b/benchmark/misc/bench-hrtime.js
@@ -0,0 +1,18 @@
+'use strict';
+
+const common = require('../common');
+
+const bench = common.createBenchmark(main, {
+  n: [1e6]
+});
+
+
+function main(conf) {
+  const n = conf.n >>> 0;
+
+  bench.start();
+  for (var i = 0; i < n; i++) {
+    process.hrtime();
+  }
+  bench.end(n);
+}
diff --git a/src/env.h b/src/env.h
index 93f7c47c9919a3..8599e1495eed20 100644
--- a/src/env.h
+++ b/src/env.h
@@ -38,6 +38,12 @@ namespace node {
 #define NODE_ISOLATE_SLOT 3
 #endif
 
+// The number of items passed to push_values_to_array_function has diminishing
+// returns around 8. This should be used at all call sites using said function.
+#ifndef NODE_PUSH_VAL_TO_ARRAY_MAX
+#define NODE_PUSH_VAL_TO_ARRAY_MAX 8
+#endif
+
 // Strings are per-isolate primitives but Environment proxies them
 // for the sake of convenience.  Strings should be ASCII-only.
 #define PER_ISOLATE_STRING_PROPERTIES(V)                                      \
@@ -231,12 +237,11 @@ 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_destroy_function, v8::Function)                               \
   V(async_hooks_init_function, v8::Function)                                  \
-  V(async_hooks_pre_function, v8::Function)                                   \
   V(async_hooks_post_function, v8::Function)                                  \
-  V(async_hooks_destroy_function, v8::Function)                               \
+  V(async_hooks_pre_function, v8::Function)                                   \
   V(binding_cache_object, v8::Object)                                         \
   V(buffer_constructor_function, v8::Function)                                \
   V(buffer_prototype_object, v8::Object)                                      \
@@ -249,6 +254,7 @@ namespace node {
   V(pipe_constructor_template, v8::FunctionTemplate)                          \
   V(process_object, v8::Object)                                               \
   V(promise_reject_function, v8::Function)                                    \
+  V(push_values_to_array_function, v8::Function)                              \
   V(script_context_constructor_template, v8::FunctionTemplate)                \
   V(script_data_constructor_function, v8::Function)                           \
   V(secure_context_constructor_template, v8::FunctionTemplate)                \
diff --git a/src/node.cc b/src/node.cc
index 4e591ff5af6053..321a2857a112c4 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1027,7 +1027,7 @@ void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
 
   CHECK(args[0]->IsFunction());
 
-  env->set_add_properties_by_index_function(args[0].As<Function>());
+  env->set_push_values_to_array_function(args[0].As<Function>());
   env->process_object()->Delete(
       FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject"));
 }
@@ -1571,28 +1571,22 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
 
   Local<Array> ary = Array::New(args.GetIsolate());
   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;
+  Local<Function> fn = env->push_values_to_array_function();
+  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
+  size_t idx = 0;
 
   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>();
-        }
-      }
+    if (w->persistent().IsEmpty())
+      continue;
+    argv[idx] = w->object();
+    if (++idx >= ARRAY_SIZE(argv)) {
+      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
+      idx = 0;
     }
   }
 
-  const size_t remainder = i % argc;
-  if (remainder > 0) {
-    HandleScope scope(env->isolate());
-    fn->Call(ctx, ary, remainder, argv).ToLocalChecked();
+  if (idx > 0) {
+    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
   }
 
   args.GetReturnValue().Set(ary);
@@ -1605,7 +1599,10 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args);
 
   Local<Array> ary = Array::New(env->isolate());
-  int i = 0;
+  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;
 
   Local<String> owner_sym = env->owner_string();
 
@@ -1616,7 +1613,14 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
     Local<Value> owner = object->Get(owner_sym);
     if (owner->IsUndefined())
       owner = object;
-    ary->Set(i++, owner);
+    argv[idx] = owner;
+    if (++idx >= ARRAY_SIZE(argv)) {
+      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
+      idx = 0;
+    }
+  }
+  if (idx > 0) {
+    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
   }
 
   args.GetReturnValue().Set(ary);
@@ -2092,22 +2096,23 @@ void Hrtime(const FunctionCallbackInfo<Value>& args) {
 
   uint64_t t = uv_hrtime();
 
-  if (args.Length() > 0) {
-    // return a time diff tuple
-    if (!args[0]->IsArray()) {
+  if (!args[1]->IsUndefined()) {
+    if (!args[1]->IsArray()) {
       return env->ThrowTypeError(
-          "process.hrtime() only accepts an Array tuple.");
+          "process.hrtime() only accepts an Array tuple");
     }
-    Local<Array> inArray = Local<Array>::Cast(args[0]);
-    uint64_t seconds = inArray->Get(0)->Uint32Value();
-    uint64_t nanos = inArray->Get(1)->Uint32Value();
-    t -= (seconds * NANOS_PER_SEC) + nanos;
+    args.GetReturnValue().Set(true);
   }
 
-  Local<Array> tuple = Array::New(env->isolate(), 2);
-  tuple->Set(0, Integer::NewFromUnsigned(env->isolate(), t / NANOS_PER_SEC));
-  tuple->Set(1, Integer::NewFromUnsigned(env->isolate(), t % NANOS_PER_SEC));
-  args.GetReturnValue().Set(tuple);
+  Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
+  uint32_t* fields = static_cast<uint32_t*>(ab->GetContents().Data());
+
+  // These three indices will contain the values for the hrtime tuple. The
+  // seconds value is broken into the upper/lower 32 bits and stored in two
+  // uint32 fields to be converted back in JS.
+  fields[0] = (t / NANOS_PER_SEC) >> 32;
+  fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
+  fields[2] = t % NANOS_PER_SEC;
 }
 
 extern "C" void node_module_register(void* m) {
@@ -2519,23 +2524,35 @@ static void EnvDeleter(Local<String> property,
 
 
 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__
   int size = 0;
   while (environ[size])
     size++;
 
-  Local<Array> envarr = Array::New(isolate, size);
+  Local<Array> envarr = Array::New(isolate);
 
   for (int i = 0; i < size; ++i) {
     const char* var = environ[i];
     const char* s = strchr(var, '=');
     const int length = s ? s - var : strlen(var);
-    Local<String> name = String::NewFromUtf8(isolate,
-                                             var,
-                                             String::kNormalString,
-                                             length);
-    envarr->Set(i, name);
+    argv[idx] = String::NewFromUtf8(isolate,
+                                    var,
+                                    String::kNormalString,
+                                    length);
+    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
   WCHAR* environment = GetEnvironmentStringsW();
@@ -2543,7 +2560,6 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
     return;  // This should not happen.
   Local<Array> envarr = Array::New(isolate);
   WCHAR* p = environment;
-  int i = 0;
   while (*p) {
     WCHAR *s;
     if (*p == L'=') {
@@ -2558,13 +2574,19 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
     }
     const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
     const size_t two_byte_buffer_len = s - p;
-    Local<String> value = String::NewFromTwoByte(isolate,
-                                                 two_byte_buffer,
-                                                 String::kNormalString,
-                                                 two_byte_buffer_len);
-    envarr->Set(i++, value);
+    argv[idx] = String::NewFromTwoByte(isolate,
+                                       two_byte_buffer,
+                                       String::kNormalString,
+                                       two_byte_buffer_len);
+    if (++idx >= ARRAY_SIZE(argv)) {
+      fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
+      idx = 0;
+    }
     p = s + wcslen(s) + 1;
   }
+  if (idx > 0) {
+    fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
+  }
   FreeEnvironmentStringsW(environment);
 #endif
 
diff --git a/src/node.js b/src/node.js
index 35a51c80640ab5..71b65497f4ba38 100644
--- a/src/node.js
+++ b/src/node.js
@@ -178,12 +178,27 @@
   }
 
   startup.setupProcessObject = function() {
-    process._setupProcessObject(setPropByIndex);
+    const _hrtime = process.hrtime;
+    const hrValues = new Uint32Array(3);
 
-    function setPropByIndex() {
+    process._setupProcessObject(pushValueToArray);
+
+    function pushValueToArray() {
       for (var i = 0; i < arguments.length; i++)
         this.push(arguments[i]);
     }
+
+    process.hrtime = function hrtime(ar) {
+      const ret = [0, 0];
+      if (_hrtime(hrValues, ar)) {
+        ret[0] = (hrValues[0] * 0x100000000 + hrValues[1]) - ar[0];
+        ret[1] = hrValues[2] - ar[1];
+      } else {
+        ret[0] = hrValues[0] * 0x100000000 + hrValues[1];
+        ret[1] = hrValues[2];
+      }
+      return ret;
+    };
   };
 
   startup.globalVariables = function() {
diff --git a/src/node_file.cc b/src/node_file.cc
index 2bd32d7daa2bd0..4941ab4467435b 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -214,6 +214,9 @@ static void After(uv_fs_t *req) {
         {
           int r;
           Local<Array> names = Array::New(env->isolate(), 0);
+          Local<Function> fn = env->push_values_to_array_function();
+          Local<Value> name_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
+          size_t name_idx = 0;
 
           for (int i = 0; ; i++) {
             uv_dirent_t ent;
@@ -229,9 +232,19 @@ static void After(uv_fs_t *req) {
               break;
             }
 
-            Local<String> name = String::NewFromUtf8(env->isolate(),
-                                                     ent.name);
-            names->Set(i, name);
+            name_argv[name_idx++] =
+                String::NewFromUtf8(env->isolate(), ent.name);
+
+            if (name_idx >= ARRAY_SIZE(name_argv)) {
+              fn->Call(env->context(), names, name_idx, name_argv)
+                  .ToLocalChecked();
+              name_idx = 0;
+            }
+          }
+
+          if (name_idx > 0) {
+            fn->Call(env->context(), names, name_idx, name_argv)
+                .ToLocalChecked();
           }
 
           argv[1] = names;
@@ -811,6 +824,9 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
     CHECK_GE(SYNC_REQ.result, 0);
     int r;
     Local<Array> names = Array::New(env->isolate(), 0);
+    Local<Function> fn = env->push_values_to_array_function();
+    Local<Value> name_v[NODE_PUSH_VAL_TO_ARRAY_MAX];
+    size_t name_idx = 0;
 
     for (int i = 0; ; i++) {
       uv_dirent_t ent;
@@ -821,9 +837,18 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
       if (r != 0)
         return env->ThrowUVException(r, "readdir", "", *path);
 
-      Local<String> name = String::NewFromUtf8(env->isolate(),
-                                               ent.name);
-      names->Set(i, name);
+
+      name_v[name_idx++] = String::NewFromUtf8(env->isolate(), ent.name);
+
+      if (name_idx >= ARRAY_SIZE(name_v)) {
+        fn->Call(env->context(), names, name_idx, name_v)
+            .ToLocalChecked();
+        name_idx = 0;
+      }
+    }
+
+    if (name_idx > 0) {
+      fn->Call(env->context(), names, name_idx, name_v).ToLocalChecked();
     }
 
     args.GetReturnValue().Set(names);
diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc
index ff3dfb26e529af..28322f95c40939 100644
--- a/src/node_http_parser.cc
+++ b/src/node_http_parser.cc
@@ -632,12 +632,23 @@ class Parser : public BaseObject {
   Local<Array> CreateHeaders() {
     // num_values_ is either -1 or the entry # of the last header
     // so num_values_ == 0 means there's a single header
-    Local<Array> headers = Array::New(env()->isolate(), 2 * num_values_);
-
-    for (int i = 0; i < num_values_; ++i) {
-      headers->Set(2 * i, fields_[i].ToString(env()));
-      headers->Set(2 * i + 1, values_[i].ToString(env()));
-    }
+    Local<Array> headers = Array::New(env()->isolate());
+    Local<Function> fn = env()->push_values_to_array_function();
+    Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX * 2];
+    int i = 0;
+
+    do {
+      size_t j = 0;
+      while (i < num_values_ && j < ARRAY_SIZE(argv) / 2) {
+        argv[j * 2] = fields_[i].ToString(env());
+        argv[j * 2 + 1] = values_[i].ToString(env());
+        i++;
+        j++;
+      }
+      if (j > 0) {
+        fn->Call(env()->context(), headers, j * 2, argv).ToLocalChecked();
+      }
+    } while (i < num_values_);
 
     return headers;
   }
diff --git a/test/parallel/test-process-getactivehandles.js b/test/parallel/test-process-getactivehandles.js
new file mode 100644
index 00000000000000..96464cf3b22fcd
--- /dev/null
+++ b/test/parallel/test-process-getactivehandles.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const common = require('../common');
+const assert = require('assert');
+const net = require('net');
+const NUM = 8;
+const connections = [];
+const clients = [];
+var clients_counter = 0;
+
+const server = net.createServer(function listener(c) {
+  connections.push(c);
+}).listen(common.PORT, function makeConnections() {
+  for (var i = 0; i < NUM; i++) {
+    net.connect(common.PORT, function connected() {
+      clientConnected(this);
+    });
+  }
+});
+
+
+function clientConnected(client) {
+  clients.push(client);
+  if (++clients_counter >= NUM)
+    checkAll();
+}
+
+
+function checkAll() {
+  const handles = process._getActiveHandles();
+
+  clients.forEach(function(item) {
+    assert.ok(handles.indexOf(item) > -1);
+    item.destroy();
+  });
+
+  connections.forEach(function(item) {
+    assert.ok(handles.indexOf(item) > -1);
+    item.end();
+  });
+
+  assert.ok(handles.indexOf(server) > -1);
+  server.close();
+}