From d13aba84996f576fab9c597209fb228518ed2e46 Mon Sep 17 00:00:00 2001 From: Brian White Date: Thu, 19 Jan 2017 22:26:18 -0500 Subject: [PATCH] buffer: improve compare() performance PR-URL: https://github.com/nodejs/node/pull/10927 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- .../buffers/buffer-compare-instance-method.js | 72 ++++++++++++++++--- lib/buffer.js | 40 ++++++----- 2 files changed, 87 insertions(+), 25 deletions(-) diff --git a/benchmark/buffers/buffer-compare-instance-method.js b/benchmark/buffers/buffer-compare-instance-method.js index 0becbeee23a7d7..bb07326f3de218 100644 --- a/benchmark/buffers/buffer-compare-instance-method.js +++ b/benchmark/buffers/buffer-compare-instance-method.js @@ -4,26 +4,80 @@ const v8 = require('v8'); const bench = common.createBenchmark(main, { size: [16, 512, 1024, 4096, 16386], + args: [1, 2, 3, 4, 5], millions: [1] }); function main(conf) { const iter = (conf.millions >>> 0) * 1e6; const size = (conf.size >>> 0); - const b0 = new Buffer(size).fill('a'); - const b1 = new Buffer(size).fill('a'); + const args = (conf.args >>> 0); + const b0 = Buffer.alloc(size, 'a'); + const b1 = Buffer.alloc(size, 'a'); + const b0Len = b0.length; + const b1Len = b1.length; + var i; b1[size - 1] = 'b'.charCodeAt(0); // Force optimization before starting the benchmark - b0.compare(b1); + switch (args) { + case 2: + b0.compare(b1, 0); + break; + case 3: + b0.compare(b1, 0, b1Len); + break; + case 4: + b0.compare(b1, 0, b1Len, 0); + break; + case 5: + b0.compare(b1, 0, b1Len, 0, b0Len); + break; + default: + b0.compare(b1); + } v8.setFlagsFromString('--allow_natives_syntax'); eval('%OptimizeFunctionOnNextCall(b0.compare)'); - b0.compare(b1); - - bench.start(); - for (var i = 0; i < iter; i++) { - b0.compare(b1); + switch (args) { + case 2: + b0.compare(b1, 0); + bench.start(); + for (i = 0; i < iter; i++) { + b0.compare(b1, 0); + } + bench.end(iter / 1e6); + break; + case 3: + b0.compare(b1, 0, b1Len); + bench.start(); + for (i = 0; i < iter; i++) { + b0.compare(b1, 0, b1Len); + } + bench.end(iter / 1e6); + break; + case 4: + b0.compare(b1, 0, b1Len, 0); + bench.start(); + for (i = 0; i < iter; i++) { + b0.compare(b1, 0, b1Len, 0); + } + bench.end(iter / 1e6); + break; + case 5: + b0.compare(b1, 0, b1Len, 0, b0Len); + bench.start(); + for (i = 0; i < iter; i++) { + b0.compare(b1, 0, b1Len, 0, b0Len); + } + bench.end(iter / 1e6); + break; + default: + b0.compare(b1); + bench.start(); + for (i = 0; i < iter; i++) { + b0.compare(b1); + } + bench.end(iter / 1e6); } - bench.end(iter / 1e6); } diff --git a/lib/buffer.js b/lib/buffer.js index fa8d1c61d4a309..299b9bc01177be 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -2,6 +2,7 @@ 'use strict'; const binding = process.binding('buffer'); +const { compare: compare_, compareOffset } = binding; const { isArrayBuffer, isSharedArrayBuffer } = process.binding('util'); const bindingObj = {}; const internalUtil = require('internal/util'); @@ -537,36 +538,43 @@ Buffer.prototype.compare = function compare(target, if (!(target instanceof Buffer)) throw new TypeError('Argument must be a Buffer'); + if (arguments.length === 1) + return compare_(this, target); if (start === undefined) start = 0; + else if (start < 0) + throw new RangeError('out of range index'); + else + start >>>= 0; + if (end === undefined) end = target.length; + else if (end > target.length) + throw new RangeError('out of range index'); + else + end >>>= 0; + if (thisStart === undefined) thisStart = 0; + else if (thisStart < 0) + throw new RangeError('out of range index'); + else + thisStart >>>= 0; + if (thisEnd === undefined) thisEnd = this.length; - - if (start < 0 || - end > target.length || - thisStart < 0 || - thisEnd > this.length) { + else if (thisEnd > this.length) throw new RangeError('out of range index'); - } + else + thisEnd >>>= 0; - if (thisStart >= thisEnd && start >= end) - return 0; if (thisStart >= thisEnd) - return -1; - if (start >= end) + return (start >= end ? 0 : -1); + else if (start >= end) return 1; - start >>>= 0; - end >>>= 0; - thisStart >>>= 0; - thisEnd >>>= 0; - - return binding.compareOffset(this, target, start, thisStart, end, thisEnd); + return compareOffset(this, target, start, thisStart, end, thisEnd); };