Skip to content

Commit 4749ec2

Browse files
mscdexaddaleax
authored andcommitted
buffer: optimize write()
PR-URL: nodejs#12361 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 3ee4a1a commit 4749ec2

File tree

2 files changed

+119
-45
lines changed

2 files changed

+119
-45
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
'use strict';
2+
3+
const common = require('../common.js');
4+
const bench = common.createBenchmark(main, {
5+
encoding: [
6+
'', 'utf8', 'ascii', 'hex', 'UCS-2', 'utf16le', 'latin1', 'binary'
7+
],
8+
args: [ '', 'offset', 'offset+length' ],
9+
len: [10, 2048],
10+
n: [1e7]
11+
});
12+
13+
function main(conf) {
14+
const len = +conf.len;
15+
const n = +conf.n;
16+
const encoding = conf.encoding;
17+
const args = conf.args;
18+
19+
const string = 'a'.repeat(len);
20+
const buf = Buffer.allocUnsafe(len);
21+
22+
var i;
23+
24+
switch (args) {
25+
case 'offset':
26+
if (encoding) {
27+
bench.start();
28+
for (i = 0; i < n; ++i) {
29+
buf.write(string, 0, encoding);
30+
}
31+
bench.end(n);
32+
} else {
33+
bench.start();
34+
for (i = 0; i < n; ++i) {
35+
buf.write(string, 0);
36+
}
37+
bench.end(n);
38+
}
39+
break;
40+
case 'offset+length':
41+
if (encoding) {
42+
bench.start();
43+
for (i = 0; i < n; ++i) {
44+
buf.write(string, 0, buf.length, encoding);
45+
}
46+
bench.end(n);
47+
} else {
48+
bench.start();
49+
for (i = 0; i < n; ++i) {
50+
buf.write(string, 0, buf.length);
51+
}
52+
bench.end(n);
53+
}
54+
break;
55+
default:
56+
if (encoding) {
57+
bench.start();
58+
for (i = 0; i < n; ++i) {
59+
buf.write(string, encoding);
60+
}
61+
bench.end(n);
62+
} else {
63+
bench.start();
64+
for (i = 0; i < n; ++i) {
65+
buf.write(string);
66+
}
67+
bench.end(n);
68+
}
69+
}
70+
}

lib/buffer.js

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,7 @@ Buffer.prototype.fill = function fill(val, start, end, encoding) {
786786
Buffer.prototype.write = function(string, offset, length, encoding) {
787787
// Buffer#write(string);
788788
if (offset === undefined) {
789-
encoding = 'utf8';
790-
length = this.length;
791-
offset = 0;
789+
return this.utf8Write(string, 0, this.length);
792790

793791
// Buffer#write(string, encoding)
794792
} else if (length === undefined && typeof offset === 'string') {
@@ -801,12 +799,17 @@ Buffer.prototype.write = function(string, offset, length, encoding) {
801799
offset = offset >>> 0;
802800
if (isFinite(length)) {
803801
length = length >>> 0;
804-
if (encoding === undefined)
805-
encoding = 'utf8';
806802
} else {
807803
encoding = length;
808804
length = undefined;
809805
}
806+
807+
var remaining = this.length - offset;
808+
if (length === undefined || length > remaining)
809+
length = remaining;
810+
811+
if (string.length > 0 && (length < 0 || offset < 0))
812+
throw new RangeError('Attempt to write outside buffer bounds');
810813
} else {
811814
// if someone is still calling the obsolete form of write(), tell them.
812815
// we don't want eg buf.write("foo", "utf8", 10) to silently turn into
@@ -815,50 +818,51 @@ Buffer.prototype.write = function(string, offset, length, encoding) {
815818
'is no longer supported');
816819
}
817820

818-
var remaining = this.length - offset;
819-
if (length === undefined || length > remaining)
820-
length = remaining;
821-
822-
if (string.length > 0 && (length < 0 || offset < 0))
823-
throw new RangeError('Attempt to write outside buffer bounds');
824-
825-
if (!encoding)
826-
encoding = 'utf8';
827-
828-
var loweredCase = false;
829-
for (;;) {
830-
switch (encoding) {
831-
case 'hex':
832-
return this.hexWrite(string, offset, length);
833-
834-
case 'utf8':
835-
case 'utf-8':
836-
return this.utf8Write(string, offset, length);
837-
838-
case 'ascii':
839-
return this.asciiWrite(string, offset, length);
821+
if (!encoding) return this.utf8Write(string, offset, length);
840822

841-
case 'latin1':
842-
case 'binary':
823+
encoding += '';
824+
switch (encoding.length) {
825+
case 4:
826+
if (encoding === 'utf8') return this.utf8Write(string, offset, length);
827+
if (encoding === 'ucs2') return this.ucs2Write(string, offset, length);
828+
encoding = encoding.toLowerCase();
829+
if (encoding === 'utf8') return this.utf8Write(string, offset, length);
830+
if (encoding === 'ucs2') return this.ucs2Write(string, offset, length);
831+
break;
832+
case 5:
833+
if (encoding === 'utf-8') return this.utf8Write(string, offset, length);
834+
if (encoding === 'ascii') return this.asciiWrite(string, offset, length);
835+
if (encoding === 'ucs-2') return this.ucs2Write(string, offset, length);
836+
encoding = encoding.toLowerCase();
837+
if (encoding === 'utf-8') return this.utf8Write(string, offset, length);
838+
if (encoding === 'ascii') return this.asciiWrite(string, offset, length);
839+
if (encoding === 'ucs-2') return this.ucs2Write(string, offset, length);
840+
break;
841+
case 7:
842+
if (encoding === 'utf16le' || encoding.toLowerCase() === 'utf16le')
843+
return this.ucs2Write(string, offset, length);
844+
break;
845+
case 8:
846+
if (encoding === 'utf-16le' || encoding.toLowerCase() === 'utf-16le')
847+
return this.ucs2Write(string, offset, length);
848+
break;
849+
case 6:
850+
if (encoding === 'latin1' || encoding === 'binary')
843851
return this.latin1Write(string, offset, length);
844-
845-
case 'base64':
846-
// Warning: maxLength not taken into account in base64Write
852+
if (encoding === 'base64')
847853
return this.base64Write(string, offset, length);
848-
849-
case 'ucs2':
850-
case 'ucs-2':
851-
case 'utf16le':
852-
case 'utf-16le':
853-
return this.ucs2Write(string, offset, length);
854-
855-
default:
856-
if (loweredCase)
857-
throw new TypeError('Unknown encoding: ' + encoding);
858-
encoding = ('' + encoding).toLowerCase();
859-
loweredCase = true;
860-
}
854+
encoding = encoding.toLowerCase();
855+
if (encoding === 'latin1' || encoding === 'binary')
856+
return this.latin1Write(string, offset, length);
857+
if (encoding === 'base64')
858+
return this.base64Write(string, offset, length);
859+
break;
860+
case 3:
861+
if (encoding === 'hex' || encoding.toLowerCase() === 'hex')
862+
return this.hexWrite(string, offset, length);
863+
break;
861864
}
865+
throw new TypeError('Unknown encoding: ' + encoding);
862866
};
863867

864868

0 commit comments

Comments
 (0)