buffer: optimize Buffer#toString()
authorBen Noordhuis <info@bnoordhuis.nl>
Sun, 21 Jun 2015 20:32:22 +0000 (22:32 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Thu, 25 Jun 2015 16:32:15 +0000 (18:32 +0200)
Break up Buffer#toString() into a fast and slow path.  The fast path
optimizes for zero-length buffers and no-arg method invocation.

The speedup for zero-length buffers is a satisfying 700%.  The no-arg
toString() operation gets faster by about 13% for a one-byte buffer.

This change exploits the fact that most Buffer#toString() calls are
plain no-arg method calls.  Rewriting the method to take no arguments
means a call doesn't go through an ArgumentsAdaptorTrampoline stack
frame in the common case.

PR-URL: https://github.com/nodejs/io.js/pull/2027
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Christian Tellnes <christian@tellnes.no>
Reviewed-By: Daniel Cousens <email@dcousens.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
benchmark/buffers/buffer-tostring.js [new file with mode: 0644]
lib/buffer.js

diff --git a/benchmark/buffers/buffer-tostring.js b/benchmark/buffers/buffer-tostring.js
new file mode 100644 (file)
index 0000000..9480520
--- /dev/null
@@ -0,0 +1,26 @@
+'use strict';
+
+const common = require('../common.js');
+
+const bench = common.createBenchmark(main, {
+  arg: [true, false],
+  len: [0, 1, 64, 1024],
+  n: [1e7]
+});
+
+function main(conf) {
+  const arg = conf.arg;
+  const len = conf.len | 0;
+  const n = conf.n | 0;
+  const buf = Buffer(len).fill(42);
+
+  bench.start();
+  if (arg) {
+    for (var i = 0; i < n; i += 1)
+      buf.toString('utf8');
+  } else {
+    for (var i = 0; i < n; i += 1)
+      buf.toString();
+  }
+  bench.end(n);
+}
index 619b735..4625515 100644 (file)
@@ -333,8 +333,7 @@ function byteLength(string, encoding) {
 
 Buffer.byteLength = byteLength;
 
-// toString(encoding, start=0, end=buffer.length)
-Buffer.prototype.toString = function(encoding, start, end) {
+function slowToString(encoding, start, end) {
   var loweredCase = false;
 
   start = start >>> 0;
@@ -376,6 +375,16 @@ Buffer.prototype.toString = function(encoding, start, end) {
         loweredCase = true;
     }
   }
+}
+
+
+Buffer.prototype.toString = function() {
+  const length = this.length | 0;
+  if (length === 0)
+    return '';
+  if (arguments.length === 0)
+    return this.utf8Slice(0, length);
+  return slowToString.apply(this, arguments);
 };