Skip to content

Commit 22b84e6

Browse files
trevnorrisisaacs
authored andcommitted
buffer: floating point read/write improvements
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
1 parent eef0ccb commit 22b84e6

File tree

13 files changed

+633
-255
lines changed

13 files changed

+633
-255
lines changed

LICENSE

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -252,38 +252,6 @@ maintained libraries. The externally maintained libraries used by Node are:
252252
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
253253
"""
254254

255-
- lib/buffer_ieee754.js. Its license follows:
256-
"""
257-
// Copyright (c) 2008, Fair Oaks Labs, Inc.
258-
// All rights reserved.
259-
//
260-
// Redistribution and use in source and binary forms, with or without
261-
// modification, are permitted provided that the following conditions are met:
262-
//
263-
// * Redistributions of source code must retain the above copyright notice,
264-
// this list of conditions and the following disclaimer.
265-
//
266-
// * Redistributions in binary form must reproduce the above copyright notice,
267-
// this list of conditions and the following disclaimer in the documentation
268-
// and/or other materials provided with the distribution.
269-
//
270-
// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
271-
// may be used to endorse or promote products derived from this software
272-
// without specific prior written permission.
273-
//
274-
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
275-
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
276-
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
277-
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
278-
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
279-
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
280-
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
281-
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
282-
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283-
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
284-
// POSSIBILITY OF SUCH DAMAGE.
285-
"""
286-
287255
- lib/punycode.js is copyright 2011 Mathias Bynens <http://mathiasbynens.be/>
288256
and released under the MIT license.
289257
"""

benchmark/_bench_timer.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* This is a simple addition to allow for higher resolution timers.
3+
* It can be used to track time for both synchronous or asynchronous
4+
* calls. For synchronous calls pass a callback function like so:
5+
*
6+
* var timer = require('./_bench_timer');
7+
*
8+
* timer('myTest', function() {
9+
* for (var i = 0; i < 1e6; i++)
10+
* // ... run something here
11+
* }
12+
* });
13+
*
14+
* For asynchronous timers just pass the name. Then run it again with
15+
* the same name to finish it:
16+
*
17+
* timer('checkAsync');
18+
* setTimeout(function() {
19+
* timer('checkAsync');
20+
* }, 300);
21+
*
22+
* When this happens all currently queued benchmarks will be paused
23+
* until the asynchronous benchmark has completed.
24+
*
25+
* If the benchmark has been run with --expose_gc then the garbage
26+
* collector will be run between each test.
27+
*
28+
* The setTimeout delay can also be changed by passing a value to
29+
* timer.delay.
30+
*/
31+
32+
33+
var store = {};
34+
var order = [];
35+
var maxLength = 0;
36+
var processing = false;
37+
var asyncQueue = 0;
38+
var GCd = typeof gc !== 'function' ? false : true;
39+
40+
function timer(name, fn) {
41+
if (maxLength < name.length)
42+
maxLength = name.length;
43+
if (!fn) {
44+
processing = false;
45+
if (!store[name]) {
46+
asyncQueue++;
47+
store[name] = process.hrtime();
48+
return;
49+
}
50+
displayTime(name, process.hrtime(store[name]));
51+
asyncQueue--;
52+
} else {
53+
store[name] = fn;
54+
order.push(name);
55+
}
56+
if (!processing && asyncQueue <= 0) {
57+
processing = true;
58+
setTimeout(run, timer.delay);
59+
}
60+
}
61+
62+
timer.delay = 100;
63+
64+
function run() {
65+
if (asyncQueue > 0 || order.length <= 0)
66+
return;
67+
if (GCd) gc();
68+
setTimeout(function() {
69+
var name = order.shift();
70+
var fn = store[name];
71+
var ini = process.hrtime();
72+
fn();
73+
ini = process.hrtime(ini);
74+
displayTime(name, ini);
75+
run();
76+
}, timer.delay);
77+
}
78+
79+
function displayTime(name, ini) {
80+
name += ': ';
81+
while (name.length < maxLength + 2)
82+
name += ' ';
83+
console.log(name + '%s \u00b5s',
84+
(~~((ini[0] * 1e6) + (ini[1] / 1e3)))
85+
.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"));
86+
}
87+
88+
module.exports = timer;

benchmark/buffer_read.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
const LEN = 1e7;
2+
const noAssert = process.argv[3] == 'true' ? true
3+
: process.argv[3] == 'false' ? false
4+
: undefined;
5+
6+
var timer = require('./_bench_timer');
7+
8+
var buff = (process.argv[2] == 'slow') ?
9+
(new require('buffer').SlowBuffer(8)) :
10+
(new Buffer(8));
11+
var i;
12+
13+
buff.writeDoubleLE(0, 0, noAssert);
14+
15+
timer('readUInt8', function() {
16+
for (i = 0; i < LEN; i++) {
17+
buff.readUInt8(0, noAssert);
18+
}
19+
});
20+
21+
timer('readUInt16LE', function() {
22+
for (i = 0; i < LEN; i++) {
23+
buff.readUInt16LE(0, noAssert);
24+
}
25+
});
26+
27+
timer('readUInt16BE', function() {
28+
for (i = 0; i < LEN; i++) {
29+
buff.readUInt16BE(0, noAssert);
30+
}
31+
});
32+
33+
timer('readUInt32LE', function() {
34+
for (i = 0; i < LEN; i++) {
35+
buff.readUInt32LE(0, noAssert);
36+
}
37+
});
38+
39+
timer('readUInt32BE', function() {
40+
for (i = 0; i < LEN; i++) {
41+
buff.readUInt32BE(0, noAssert);
42+
}
43+
});
44+
45+
timer('readInt8', function() {
46+
for (i = 0; i < LEN; i++) {
47+
buff.readInt8(0, noAssert);
48+
}
49+
});
50+
51+
timer('readInt16LE', function() {
52+
for (i = 0; i < LEN; i++) {
53+
buff.readInt16LE(0, noAssert);
54+
}
55+
});
56+
57+
timer('readInt16BE', function() {
58+
for (i = 0; i < LEN; i++) {
59+
buff.readInt16BE(0, noAssert);
60+
}
61+
});
62+
63+
timer('readInt32LE', function() {
64+
for (i = 0; i < LEN; i++) {
65+
buff.readInt32LE(0, noAssert);
66+
}
67+
});
68+
69+
timer('readInt32BE', function() {
70+
for (i = 0; i < LEN; i++) {
71+
buff.readInt32BE(0, noAssert);
72+
}
73+
});
74+
75+
timer('readFloatLE', function() {
76+
for (i = 0; i < LEN; i++) {
77+
buff.readFloatLE(0, noAssert);
78+
}
79+
});
80+
81+
timer('readFloatBE', function() {
82+
for (i = 0; i < LEN; i++) {
83+
buff.readFloatBE(0, noAssert);
84+
}
85+
});
86+
87+
timer('readDoubleLE', function() {
88+
for (i = 0; i < LEN; i++) {
89+
buff.readDoubleLE(0, noAssert);
90+
}
91+
});
92+
93+
timer('readDoubleBE', function() {
94+
for (i = 0; i < LEN; i++) {
95+
buff.readDoubleBE(0, noAssert);
96+
}
97+
});

benchmark/buffer_write.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
const LEN = 1e7;
2+
3+
const INT8 = 0x7f;
4+
const INT16 = 0x7fff;
5+
const INT32 = 0x7fffffff;
6+
const UINT8 = INT8 * 2;
7+
const UINT16 = INT16 * 2;
8+
const UINT32 = INT32 * 2;
9+
10+
const noAssert = process.argv[3] == 'true' ? true
11+
: process.argv[3] == 'false' ? false
12+
: undefined;
13+
14+
var timer = require('./_bench_timer');
15+
16+
var buff = (process.argv[2] == 'slow') ?
17+
(new require('buffer').SlowBuffer(8)) :
18+
(new Buffer(8));
19+
var i;
20+
21+
timer('writeUInt8', function() {
22+
for (i = 0; i < LEN; i++) {
23+
buff.writeUInt8(i % UINT8, 0, noAssert);
24+
}
25+
});
26+
27+
timer('writeUInt16LE', function() {
28+
for (i = 0; i < LEN; i++) {
29+
buff.writeUInt16LE(i % UINT16, 0, noAssert);
30+
}
31+
});
32+
33+
timer('writeUInt16BE', function() {
34+
for (i = 0; i < LEN; i++) {
35+
buff.writeUInt16BE(i % UINT16, 0, noAssert);
36+
}
37+
});
38+
39+
timer('writeUInt32LE', function() {
40+
for (i = 0; i < LEN; i++) {
41+
buff.writeUInt32LE(i % UINT32, 0, noAssert);
42+
}
43+
});
44+
45+
timer('writeUInt32BE', function() {
46+
for (i = 0; i < LEN; i++) {
47+
buff.writeUInt32BE(i % UINT32, 0, noAssert);
48+
}
49+
});
50+
51+
timer('writeInt8', function() {
52+
for (i = 0; i < LEN; i++) {
53+
buff.writeInt8(i % INT8, 0, noAssert);
54+
}
55+
});
56+
57+
timer('writeInt16LE', function() {
58+
for (i = 0; i < LEN; i++) {
59+
buff.writeInt16LE(i % INT16, 0, noAssert);
60+
}
61+
});
62+
63+
timer('writeInt16BE', function() {
64+
for (i = 0; i < LEN; i++) {
65+
buff.writeInt16BE(i % INT16, 0, noAssert);
66+
}
67+
});
68+
69+
timer('writeInt32LE', function() {
70+
for (i = 0; i < LEN; i++) {
71+
buff.writeInt32LE(i % INT32, 0, noAssert);
72+
}
73+
});
74+
75+
timer('writeInt32BE', function() {
76+
for (i = 0; i < LEN; i++) {
77+
buff.writeInt32BE(i % INT32, 0, noAssert);
78+
}
79+
});
80+
81+
timer('writeFloatLE', function() {
82+
for (i = 0; i < LEN; i++) {
83+
buff.writeFloatLE(i * 0.1, 0, noAssert);
84+
}
85+
});
86+
87+
timer('writeFloatBE', function() {
88+
for (i = 0; i < LEN; i++) {
89+
buff.writeFloatBE(i * 0.1, 0, noAssert);
90+
}
91+
});
92+
93+
timer('writeDoubleLE', function() {
94+
for (i = 0; i < LEN; i++) {
95+
buff.writeDoubleLE(i * 0.1, 0, noAssert);
96+
}
97+
});
98+
99+
timer('writeDoubleBE', function() {
100+
for (i = 0; i < LEN; i++) {
101+
buff.writeDoubleBE(i * 0.1, 0, noAssert);
102+
}
103+
});

0 commit comments

Comments
 (0)