buffer: optimize common encoding cases

String#toLowerCase() is incredibly slow and was costing a 15-30%
performance hit for Buffers less than 1KB. Now instead it'll attempt to
find the correct encoding directly from the passed encoding, only then
afterwards it'll lowercase.

The optimization for not passing any encoding at all is still at the top
of the method.

At most this may add 10% performance hit for passing a mixed case
encoding.
This commit is contained in:
Trevor Norris 2013-09-09 19:39:21 -07:00
parent 204228b57f
commit 59dac01e4e

View File

@ -202,40 +202,46 @@ Buffer.prototype.parent = undefined;
// toString(encoding, start=0, end=buffer.length)
Buffer.prototype.toString = function(encoding, start, end) {
encoding = !!encoding ? (encoding + '').toLowerCase() : 'utf8';
var loweredCase = false;
start = ~~start;
end = util.isUndefined(end) ? this.length : ~~end;
start = start >>> 0;
end = util.isUndefined(end) ? this.length : end >>> 0;
if (!encoding) encoding = 'utf8';
if (start < 0) start = 0;
if (end > this.length) end = this.length;
if (end <= start) return '';
switch (encoding) {
case 'hex':
return this.hexSlice(start, end);
while (true) {
switch (encoding) {
case 'hex':
return this.hexSlice(start, end);
case 'utf8':
case 'utf-8':
return this.utf8Slice(start, end);
case 'utf8':
case 'utf-8':
return this.utf8Slice(start, end);
case 'ascii':
return this.asciiSlice(start, end);
case 'ascii':
return this.asciiSlice(start, end);
case 'binary':
return this.binarySlice(start, end);
case 'binary':
return this.binarySlice(start, end);
case 'base64':
return this.base64Slice(start, end);
case 'base64':
return this.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return this.ucs2Slice(start, end);
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return this.ucs2Slice(start, end);
default:
throw new TypeError('Unknown encoding: ' + encoding);
default:
if (loweredCase)
throw new TypeError('Unknown encoding: ' + encoding);
encoding = (encoding + '').toLowerCase();
loweredCase = true;
}
}
};