mirror of https://github.com/lukechilds/node.git
Browse Source
Improvements: * floating point operations are approx 4x's faster * Now write quiet NaN's * all read/write on floating point now done in C, so no more need for lib/buffer_ieee754.js * float values have more accurate min/max value checks * add additional benchmarks for buffers read/write * created benchmark/_bench_timer.js which is a simple library that can be included into any benchmark and provides an intelligent tracker for sync and async tests * add benchmarks for DataView set methods * add checks and tests to make sure offset is greater than 0v0.9.7-release
Trevor Norris
12 years ago
committed by
isaacs
13 changed files with 633 additions and 255 deletions
@ -0,0 +1,88 @@ |
|||
/* |
|||
* This is a simple addition to allow for higher resolution timers. |
|||
* It can be used to track time for both synchronous or asynchronous |
|||
* calls. For synchronous calls pass a callback function like so: |
|||
* |
|||
* var timer = require('./_bench_timer'); |
|||
* |
|||
* timer('myTest', function() { |
|||
* for (var i = 0; i < 1e6; i++) |
|||
* // ... run something here
|
|||
* } |
|||
* }); |
|||
* |
|||
* For asynchronous timers just pass the name. Then run it again with |
|||
* the same name to finish it: |
|||
* |
|||
* timer('checkAsync'); |
|||
* setTimeout(function() { |
|||
* timer('checkAsync'); |
|||
* }, 300); |
|||
* |
|||
* When this happens all currently queued benchmarks will be paused |
|||
* until the asynchronous benchmark has completed. |
|||
* |
|||
* If the benchmark has been run with --expose_gc then the garbage |
|||
* collector will be run between each test. |
|||
* |
|||
* The setTimeout delay can also be changed by passing a value to |
|||
* timer.delay. |
|||
*/ |
|||
|
|||
|
|||
var store = {}; |
|||
var order = []; |
|||
var maxLength = 0; |
|||
var processing = false; |
|||
var asyncQueue = 0; |
|||
var GCd = typeof gc !== 'function' ? false : true; |
|||
|
|||
function timer(name, fn) { |
|||
if (maxLength < name.length) |
|||
maxLength = name.length; |
|||
if (!fn) { |
|||
processing = false; |
|||
if (!store[name]) { |
|||
asyncQueue++; |
|||
store[name] = process.hrtime(); |
|||
return; |
|||
} |
|||
displayTime(name, process.hrtime(store[name])); |
|||
asyncQueue--; |
|||
} else { |
|||
store[name] = fn; |
|||
order.push(name); |
|||
} |
|||
if (!processing && asyncQueue <= 0) { |
|||
processing = true; |
|||
setTimeout(run, timer.delay); |
|||
} |
|||
} |
|||
|
|||
timer.delay = 100; |
|||
|
|||
function run() { |
|||
if (asyncQueue > 0 || order.length <= 0) |
|||
return; |
|||
if (GCd) gc(); |
|||
setTimeout(function() { |
|||
var name = order.shift(); |
|||
var fn = store[name]; |
|||
var ini = process.hrtime(); |
|||
fn(); |
|||
ini = process.hrtime(ini); |
|||
displayTime(name, ini); |
|||
run(); |
|||
}, timer.delay); |
|||
} |
|||
|
|||
function displayTime(name, ini) { |
|||
name += ': '; |
|||
while (name.length < maxLength + 2) |
|||
name += ' '; |
|||
console.log(name + '%s \u00b5s', |
|||
(~~((ini[0] * 1e6) + (ini[1] / 1e3))) |
|||
.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")); |
|||
} |
|||
|
|||
module.exports = timer; |
@ -0,0 +1,97 @@ |
|||
const LEN = 1e7; |
|||
const noAssert = process.argv[3] == 'true' ? true |
|||
: process.argv[3] == 'false' ? false |
|||
: undefined; |
|||
|
|||
var timer = require('./_bench_timer'); |
|||
|
|||
var buff = (process.argv[2] == 'slow') ? |
|||
(new require('buffer').SlowBuffer(8)) : |
|||
(new Buffer(8)); |
|||
var i; |
|||
|
|||
buff.writeDoubleLE(0, 0, noAssert); |
|||
|
|||
timer('readUInt8', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readUInt8(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readUInt16LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readUInt16LE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readUInt16BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readUInt16BE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readUInt32LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readUInt32LE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readUInt32BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readUInt32BE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readInt8', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readInt8(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readInt16LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readInt16LE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readInt16BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readInt16BE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readInt32LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readInt32LE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readInt32BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readInt32BE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readFloatLE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readFloatLE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readFloatBE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readFloatBE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readDoubleLE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readDoubleLE(0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('readDoubleBE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.readDoubleBE(0, noAssert); |
|||
} |
|||
}); |
@ -0,0 +1,103 @@ |
|||
const LEN = 1e7; |
|||
|
|||
const INT8 = 0x7f; |
|||
const INT16 = 0x7fff; |
|||
const INT32 = 0x7fffffff; |
|||
const UINT8 = INT8 * 2; |
|||
const UINT16 = INT16 * 2; |
|||
const UINT32 = INT32 * 2; |
|||
|
|||
const noAssert = process.argv[3] == 'true' ? true |
|||
: process.argv[3] == 'false' ? false |
|||
: undefined; |
|||
|
|||
var timer = require('./_bench_timer'); |
|||
|
|||
var buff = (process.argv[2] == 'slow') ? |
|||
(new require('buffer').SlowBuffer(8)) : |
|||
(new Buffer(8)); |
|||
var i; |
|||
|
|||
timer('writeUInt8', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeUInt8(i % UINT8, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeUInt16LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeUInt16LE(i % UINT16, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeUInt16BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeUInt16BE(i % UINT16, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeUInt32LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeUInt32LE(i % UINT32, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeUInt32BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeUInt32BE(i % UINT32, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeInt8', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeInt8(i % INT8, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeInt16LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeInt16LE(i % INT16, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeInt16BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeInt16BE(i % INT16, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeInt32LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeInt32LE(i % INT32, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeInt32BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeInt32BE(i % INT32, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeFloatLE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeFloatLE(i * 0.1, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeFloatBE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeFloatBE(i * 0.1, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeDoubleLE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeDoubleLE(i * 0.1, 0, noAssert); |
|||
} |
|||
}); |
|||
|
|||
timer('writeDoubleBE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
buff.writeDoubleBE(i * 0.1, 0, noAssert); |
|||
} |
|||
}); |
@ -0,0 +1,104 @@ |
|||
const LEN = 1e7; |
|||
|
|||
const INT8 = 0x7f; |
|||
const INT16 = 0x7fff; |
|||
const INT32 = 0x7fffffff; |
|||
const UINT8 = INT8 * 2; |
|||
const UINT16 = INT16 * 2; |
|||
const UINT32 = INT32 * 2; |
|||
|
|||
const noAssert = process.argv[3] == 'true' ? true |
|||
: process.argv[3] == 'false' ? false |
|||
: undefined; |
|||
|
|||
var timer = require('./_bench_timer'); |
|||
|
|||
var buff = (process.argv[2] == 'slow') ? |
|||
(new require('buffer').SlowBuffer(8)) : |
|||
(new Buffer(8)); |
|||
var dv = new DataView(buff); |
|||
var i; |
|||
|
|||
timer('setUint8', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setUint8(0, i % UINT8); |
|||
} |
|||
}); |
|||
|
|||
timer('setUint16 - LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setUint16(0, i % UINT16, true); |
|||
} |
|||
}); |
|||
|
|||
timer('setUint16 - BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setUint16(0, i % UINT16); |
|||
} |
|||
}); |
|||
|
|||
timer('setUint32 - LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setUint32(0, i % UINT32, true); |
|||
} |
|||
}); |
|||
|
|||
timer('setUint32 - BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setUint32(0, i % UINT32); |
|||
} |
|||
}); |
|||
|
|||
timer('setInt8', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setInt8(0, i % INT8); |
|||
} |
|||
}); |
|||
|
|||
timer('setInt16 - LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setInt16(0, i % INT16, true); |
|||
} |
|||
}); |
|||
|
|||
timer('setInt16 - BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setInt16(0, i % INT16); |
|||
} |
|||
}); |
|||
|
|||
timer('setInt32 - LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setInt32(0, i % INT32, true); |
|||
} |
|||
}); |
|||
|
|||
timer('setInt32 - BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setInt32(0, i % INT32); |
|||
} |
|||
}); |
|||
|
|||
timer('setFloat32 - LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setFloat32(0, i * 0.1, true); |
|||
} |
|||
}); |
|||
|
|||
timer('setFloat32 - BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setFloat32(0, i * 0.1); |
|||
} |
|||
}); |
|||
|
|||
timer('setFloat64 - LE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setFloat64(0, i * 0.1, true); |
|||
} |
|||
}); |
|||
|
|||
timer('setFloat64 - BE', function() { |
|||
for (i = 0; i < LEN; i++) { |
|||
dv.setFloat64(0, i * 0.1); |
|||
} |
|||
}); |
@ -1,116 +0,0 @@ |
|||
// Copyright (c) 2008, Fair Oaks Labs, Inc.
|
|||
// All rights reserved.
|
|||
//
|
|||
// Redistribution and use in source and binary forms, with or without
|
|||
// modification, are permitted provided that the following conditions are met:
|
|||
//
|
|||
// * Redistributions of source code must retain the above copyright notice,
|
|||
// this list of conditions and the following disclaimer.
|
|||
//
|
|||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|||
// this list of conditions and the following disclaimer in the documentation
|
|||
// and/or other materials provided with the distribution.
|
|||
//
|
|||
// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
|
|||
// may be used to endorse or promote products derived from this software
|
|||
// without specific prior written permission.
|
|||
//
|
|||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|||
// POSSIBILITY OF SUCH DAMAGE.
|
|||
//
|
|||
//
|
|||
// Modifications to writeIEEE754 to support negative zeroes made by Brian White
|
|||
|
|||
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) { |
|||
var e, m, |
|||
eLen = nBytes * 8 - mLen - 1, |
|||
eMax = (1 << eLen) - 1, |
|||
eBias = eMax >> 1, |
|||
nBits = -7, |
|||
i = isBE ? 0 : (nBytes - 1), |
|||
d = isBE ? 1 : -1, |
|||
s = buffer[offset + i]; |
|||
|
|||
i += d; |
|||
|
|||
e = s & ((1 << (-nBits)) - 1); |
|||
s >>= (-nBits); |
|||
nBits += eLen; |
|||
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); |
|||
|
|||
m = e & ((1 << (-nBits)) - 1); |
|||
e >>= (-nBits); |
|||
nBits += mLen; |
|||
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); |
|||
|
|||
if (e === 0) { |
|||
e = 1 - eBias; |
|||
} else if (e === eMax) { |
|||
return m ? NaN : ((s ? -1 : 1) * Infinity); |
|||
} else { |
|||
m = m + Math.pow(2, mLen); |
|||
e = e - eBias; |
|||
} |
|||
return (s ? -1 : 1) * m * Math.pow(2, e - mLen); |
|||
}; |
|||
|
|||
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) { |
|||
var e, m, c, |
|||
eLen = nBytes * 8 - mLen - 1, |
|||
eMax = (1 << eLen) - 1, |
|||
eBias = eMax >> 1, |
|||
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), |
|||
i = isBE ? (nBytes - 1) : 0, |
|||
d = isBE ? -1 : 1, |
|||
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; |
|||
|
|||
value = Math.abs(value); |
|||
|
|||
if (isNaN(value) || value === Infinity) { |
|||
m = isNaN(value) ? 1 : 0; |
|||
e = eMax; |
|||
} else { |
|||
e = Math.floor(Math.log(value) / Math.LN2); |
|||
if (value * (c = Math.pow(2, -e)) < 1) { |
|||
e--; |
|||
c *= 2; |
|||
} |
|||
if (e + eBias >= 1) { |
|||
value += rt / c; |
|||
} else { |
|||
value += rt * Math.pow(2, 1 - eBias); |
|||
} |
|||
if (value * c >= 2) { |
|||
e++; |
|||
c /= 2; |
|||
} |
|||
|
|||
if (e + eBias >= eMax) { |
|||
m = 0; |
|||
e = eMax; |
|||
} else if (e + eBias >= 1) { |
|||
m = (value * c - 1) * Math.pow(2, mLen); |
|||
e = e + eBias; |
|||
} else { |
|||
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); |
|||
e = 0; |
|||
} |
|||
} |
|||
|
|||
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); |
|||
|
|||
e = (e << mLen) | m; |
|||
eLen += mLen; |
|||
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); |
|||
|
|||
buffer[offset + i - d] |= s * 128; |
|||
}; |
Loading…
Reference in new issue