Skip to content

Commit

Permalink
buffer: optimize write()
Browse files Browse the repository at this point in the history
PR-URL: nodejs#12361
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
  • Loading branch information
mscdex authored and addaleax committed Apr 14, 2017
1 parent 3ee4a1a commit 4749ec2
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 45 deletions.
70 changes: 70 additions & 0 deletions benchmark/buffers/buffer-write-string.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict';

const common = require('../common.js');
const bench = common.createBenchmark(main, {
encoding: [
'', 'utf8', 'ascii', 'hex', 'UCS-2', 'utf16le', 'latin1', 'binary'
],
args: [ '', 'offset', 'offset+length' ],
len: [10, 2048],
n: [1e7]
});

function main(conf) {
const len = +conf.len;
const n = +conf.n;
const encoding = conf.encoding;
const args = conf.args;

const string = 'a'.repeat(len);
const buf = Buffer.allocUnsafe(len);

var i;

switch (args) {
case 'offset':
if (encoding) {
bench.start();
for (i = 0; i < n; ++i) {
buf.write(string, 0, encoding);
}
bench.end(n);
} else {
bench.start();
for (i = 0; i < n; ++i) {
buf.write(string, 0);
}
bench.end(n);
}
break;
case 'offset+length':
if (encoding) {
bench.start();
for (i = 0; i < n; ++i) {
buf.write(string, 0, buf.length, encoding);
}
bench.end(n);
} else {
bench.start();
for (i = 0; i < n; ++i) {
buf.write(string, 0, buf.length);
}
bench.end(n);
}
break;
default:
if (encoding) {
bench.start();
for (i = 0; i < n; ++i) {
buf.write(string, encoding);
}
bench.end(n);
} else {
bench.start();
for (i = 0; i < n; ++i) {
buf.write(string);
}
bench.end(n);
}
}
}
94 changes: 49 additions & 45 deletions lib/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -786,9 +786,7 @@ Buffer.prototype.fill = function fill(val, start, end, encoding) {
Buffer.prototype.write = function(string, offset, length, encoding) {
// Buffer#write(string);
if (offset === undefined) {
encoding = 'utf8';
length = this.length;
offset = 0;
return this.utf8Write(string, 0, this.length);

// Buffer#write(string, encoding)
} else if (length === undefined && typeof offset === 'string') {
Expand All @@ -801,12 +799,17 @@ Buffer.prototype.write = function(string, offset, length, encoding) {
offset = offset >>> 0;
if (isFinite(length)) {
length = length >>> 0;
if (encoding === undefined)
encoding = 'utf8';
} else {
encoding = length;
length = undefined;
}

var remaining = this.length - offset;
if (length === undefined || length > remaining)
length = remaining;

if (string.length > 0 && (length < 0 || offset < 0))
throw new RangeError('Attempt to write outside buffer bounds');
} else {
// if someone is still calling the obsolete form of write(), tell them.
// we don't want eg buf.write("foo", "utf8", 10) to silently turn into
Expand All @@ -815,50 +818,51 @@ Buffer.prototype.write = function(string, offset, length, encoding) {
'is no longer supported');
}

var remaining = this.length - offset;
if (length === undefined || length > remaining)
length = remaining;

if (string.length > 0 && (length < 0 || offset < 0))
throw new RangeError('Attempt to write outside buffer bounds');

if (!encoding)
encoding = 'utf8';

var loweredCase = false;
for (;;) {
switch (encoding) {
case 'hex':
return this.hexWrite(string, offset, length);

case 'utf8':
case 'utf-8':
return this.utf8Write(string, offset, length);

case 'ascii':
return this.asciiWrite(string, offset, length);
if (!encoding) return this.utf8Write(string, offset, length);

case 'latin1':
case 'binary':
encoding += '';
switch (encoding.length) {
case 4:
if (encoding === 'utf8') return this.utf8Write(string, offset, length);
if (encoding === 'ucs2') return this.ucs2Write(string, offset, length);
encoding = encoding.toLowerCase();
if (encoding === 'utf8') return this.utf8Write(string, offset, length);
if (encoding === 'ucs2') return this.ucs2Write(string, offset, length);
break;
case 5:
if (encoding === 'utf-8') return this.utf8Write(string, offset, length);
if (encoding === 'ascii') return this.asciiWrite(string, offset, length);
if (encoding === 'ucs-2') return this.ucs2Write(string, offset, length);
encoding = encoding.toLowerCase();
if (encoding === 'utf-8') return this.utf8Write(string, offset, length);
if (encoding === 'ascii') return this.asciiWrite(string, offset, length);
if (encoding === 'ucs-2') return this.ucs2Write(string, offset, length);
break;
case 7:
if (encoding === 'utf16le' || encoding.toLowerCase() === 'utf16le')
return this.ucs2Write(string, offset, length);
break;
case 8:
if (encoding === 'utf-16le' || encoding.toLowerCase() === 'utf-16le')
return this.ucs2Write(string, offset, length);
break;
case 6:
if (encoding === 'latin1' || encoding === 'binary')
return this.latin1Write(string, offset, length);

case 'base64':
// Warning: maxLength not taken into account in base64Write
if (encoding === 'base64')
return this.base64Write(string, offset, length);

case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return this.ucs2Write(string, offset, length);

default:
if (loweredCase)
throw new TypeError('Unknown encoding: ' + encoding);
encoding = ('' + encoding).toLowerCase();
loweredCase = true;
}
encoding = encoding.toLowerCase();
if (encoding === 'latin1' || encoding === 'binary')
return this.latin1Write(string, offset, length);
if (encoding === 'base64')
return this.base64Write(string, offset, length);
break;
case 3:
if (encoding === 'hex' || encoding.toLowerCase() === 'hex')
return this.hexWrite(string, offset, length);
break;
}
throw new TypeError('Unknown encoding: ' + encoding);
};


Expand Down

0 comments on commit 4749ec2

Please sign in to comment.