Skip to content

Commit

Permalink
buffer: floating point read/write improvements
Browse files Browse the repository at this point in the history
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 0
  • Loading branch information
trevnorris authored and isaacs committed Jan 16, 2013
1 parent eef0ccb commit 22b84e6
Show file tree
Hide file tree
Showing 13 changed files with 633 additions and 255 deletions.
32 changes: 0 additions & 32 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -252,38 +252,6 @@ maintained libraries. The externally maintained libraries used by Node are:
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

- lib/buffer_ieee754.js. Its license follows:
"""
// 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.
"""

- lib/punycode.js is copyright 2011 Mathias Bynens <http://mathiasbynens.be/>
and released under the MIT license.
"""
Expand Down
88 changes: 88 additions & 0 deletions benchmark/_bench_timer.js
Original file line number Diff line number Diff line change
@@ -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;
97 changes: 97 additions & 0 deletions benchmark/buffer_read.js
Original file line number Diff line number Diff line change
@@ -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);
}
});
103 changes: 103 additions & 0 deletions benchmark/buffer_write.js
Original file line number Diff line number Diff line change
@@ -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);
}
});
Loading

0 comments on commit 22b84e6

Please sign in to comment.