-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
buffer: add Buffer.prototype.compare by offset
Adds additional `targetStart`, `targetEnd`, `sourceStart, and `sourceEnd` arguments to `Buffer.prototype.compare` to allow comparison of sub-ranges of two Buffers without requiring Buffer.prototype.slice() Fixes: #521 PR-URL: #5880 Reviewed-By: Trevor Norris <[email protected]>
- Loading branch information
Showing
5 changed files
with
248 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
'use strict'; | ||
const common = require('../common.js'); | ||
const v8 = require('v8'); | ||
|
||
const bench = common.createBenchmark(main, { | ||
method: ['offset', 'slice'], | ||
size: [16, 512, 1024, 4096, 16386], | ||
millions: [1] | ||
}); | ||
|
||
function compareUsingSlice(b0, b1, len, iter) { | ||
|
||
// Force optimization before starting the benchmark | ||
Buffer.compare(b0.slice(1, len), b1.slice(1, len)); | ||
v8.setFlagsFromString('--allow_natives_syntax'); | ||
eval('%OptimizeFunctionOnNextCall(Buffer.compare)'); | ||
eval('%OptimizeFunctionOnNextCall(b0.slice)'); | ||
eval('%OptimizeFunctionOnNextCall(b1.slice)'); | ||
Buffer.compare(b0.slice(1, len), b1.slice(1, len)); | ||
doCompareUsingSlice(b0, b1, len, iter); | ||
} | ||
|
||
function doCompareUsingSlice(b0, b1, len, iter) { | ||
var i; | ||
bench.start(); | ||
for (i = 0; i < iter; i++) | ||
Buffer.compare(b0.slice(1, len), b1.slice(1, len)); | ||
bench.end(iter / 1e6); | ||
} | ||
|
||
function compareUsingOffset(b0, b1, len, iter) { | ||
len = len + 1; | ||
// Force optimization before starting the benchmark | ||
b0.compare(b1, 1, len, 1, len); | ||
v8.setFlagsFromString('--allow_natives_syntax'); | ||
eval('%OptimizeFunctionOnNextCall(b0.compare)'); | ||
b0.compare(b1, 1, len, 1, len); | ||
doCompareUsingOffset(b0, b1, len, iter); | ||
} | ||
|
||
function doCompareUsingOffset(b0, b1, len, iter) { | ||
var i; | ||
bench.start(); | ||
for (i = 0; i < iter; i++) | ||
b0.compare(b1, 1, len, 1, len); | ||
bench.end(iter / 1e6); | ||
} | ||
|
||
function main(conf) { | ||
const iter = (conf.millions >>> 0) * 1e6; | ||
const size = (conf.size >>> 0); | ||
const method = conf.method === 'slice' ? | ||
compareUsingSlice : compareUsingOffset; | ||
method(Buffer.alloc(size, 'a'), | ||
Buffer.alloc(size, 'b'), | ||
size >> 1, | ||
iter); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
'use strict'; | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
|
||
const a = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); | ||
const b = Buffer.from([5, 6, 7, 8, 9, 0, 1, 2, 3, 4]); | ||
|
||
assert.equal(-1, a.compare(b)); | ||
|
||
// Equivalent to a.compare(b). | ||
assert.equal(-1, a.compare(b, 0)); | ||
assert.equal(-1, a.compare(b, '0')); | ||
|
||
// Equivalent to a.compare(b). | ||
assert.equal(-1, a.compare(b, 0, undefined, 0)); | ||
|
||
// Zero-length targer, return 1 | ||
assert.equal(1, a.compare(b, 0, 0, 0)); | ||
assert.equal(1, a.compare(b, '0', '0', '0')); | ||
|
||
// Equivalent to Buffer.compare(a, b.slice(6, 10)) | ||
assert.equal(1, a.compare(b, 6, 10)); | ||
|
||
// Zero-length source, return -1 | ||
assert.equal(-1, a.compare(b, 6, 10, 0, 0)); | ||
|
||
// Equivalent to Buffer.compare(a.slice(4), b.slice(0, 5)) | ||
assert.equal(1, a.compare(b, 0, 5, 4)); | ||
|
||
// Equivalent to Buffer.compare(a.slice(1), b.slice(5)) | ||
assert.equal(1, a.compare(b, 5, undefined, 1)); | ||
|
||
// Equivalent to Buffer.compare(a.slice(2), b.slice(2, 4)) | ||
assert.equal(-1, a.compare(b, 2, 4, 2)); | ||
|
||
// Equivalent to Buffer.compare(a.slice(4), b.slice(0, 7)) | ||
assert.equal(-1, a.compare(b, 0, 7, 4)); | ||
|
||
// Equivalent to Buffer.compare(a.slice(4, 6), b.slice(0, 7)); | ||
assert.equal(-1, a.compare(b, 0, 7, 4, 6)); | ||
|
||
// zero length target | ||
assert.equal(1, a.compare(b, 0, null)); | ||
|
||
// coerces to targetEnd == 5 | ||
assert.equal(-1, a.compare(b, 0, {valueOf: () => 5})); | ||
|
||
// zero length target | ||
assert.equal(1, a.compare(b, Infinity, -Infinity)); | ||
|
||
// zero length target because default for targetEnd <= targetSource | ||
assert.equal(1, a.compare(b, '0xff')); | ||
|
||
const oor = /out of range index/; | ||
|
||
assert.throws(() => a.compare(b, 0, 100, 0), oor); | ||
assert.throws(() => a.compare(b, 0, 1, 0, 100), oor); | ||
assert.throws(() => a.compare(b, -1), oor); | ||
assert.throws(() => a.compare(b, 0, '0xff'), oor); | ||
assert.throws(() => a.compare(b, 0, Infinity), oor); | ||
assert.throws(() => a.compare(b, -Infinity, Infinity), oor); | ||
assert.throws(() => a.compare(), /Argument must be a Buffer/); |