buffer: speed up base64 encoding by 20%
Remove a lot of branches from the inner loop. Speeds up buf.toString('base64') by about 20%. Before: $ time out/Release/node benchmark/buffer-base64-encode.js real 0m6.607s user 0m5.508s sys 0m1.088s After: $ time out/Release/node benchmark/buffer-base64-encode.js real 0m5.520s user 0m4.520s sys 0m0.992s
This commit is contained in:
parent
192192a09e
commit
a329729537
27
benchmark/buffer-base64-encode.js
Normal file
27
benchmark/buffer-base64-encode.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright Joyent, Inc. and other Node contributors.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
// persons to whom the Software is furnished to do so, subject to the
|
||||||
|
// following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||||
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
var N = 64*1024*1024
|
||||||
|
var b = Buffer(N);
|
||||||
|
var s = '';
|
||||||
|
for (var i = 0; i < 256; ++i) s += String.fromCharCode(i);
|
||||||
|
for (var i = 0; i < N; i += 256) b.write(s, i, 256, 'ascii');
|
||||||
|
for (var i = 0; i < 32; ++i) b.toString('base64');
|
@ -276,9 +276,6 @@ Handle<Value> Buffer::Ucs2Slice(const Arguments &args) {
|
|||||||
return scope.Close(string);
|
return scope.Close(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
|
||||||
"0123456789+/";
|
|
||||||
|
|
||||||
// supports regular and URL-safe base64
|
// supports regular and URL-safe base64
|
||||||
static const int unbase64_table[] =
|
static const int unbase64_table[] =
|
||||||
@ -307,69 +304,65 @@ Handle<Value> Buffer::Base64Slice(const Arguments &args) {
|
|||||||
Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
|
Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
|
||||||
SLICE_ARGS(args[0], args[1])
|
SLICE_ARGS(args[0], args[1])
|
||||||
|
|
||||||
int n = end - start;
|
unsigned slen = end - start;
|
||||||
int out_len = (n + 2 - ((n + 2) % 3)) / 3 * 4;
|
const char* src = parent->data_ + start;
|
||||||
char *out = new char[out_len];
|
|
||||||
|
|
||||||
uint8_t bitbuf[3];
|
unsigned dlen = (slen + 2 - ((slen + 2) % 3)) / 3 * 4;
|
||||||
int i = start; // data() index
|
char* dst = new char[dlen];
|
||||||
int j = 0; // out index
|
|
||||||
char c;
|
|
||||||
bool b1_oob, b2_oob;
|
|
||||||
|
|
||||||
while (i < end) {
|
unsigned a;
|
||||||
bitbuf[0] = parent->data_[i++];
|
unsigned b;
|
||||||
|
unsigned c;
|
||||||
|
unsigned i;
|
||||||
|
unsigned k;
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
if (i < end) {
|
static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
bitbuf[1] = parent->data_[i];
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
b1_oob = false;
|
"0123456789+/";
|
||||||
} else {
|
|
||||||
bitbuf[1] = 0;
|
|
||||||
b1_oob = true;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i < end) {
|
i = 0;
|
||||||
bitbuf[2] = parent->data_[i];
|
k = 0;
|
||||||
b2_oob = false;
|
n = slen / 3 * 3;
|
||||||
} else {
|
|
||||||
bitbuf[2] = 0;
|
|
||||||
b2_oob = true;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
|
|
||||||
|
while (i < n) {
|
||||||
|
a = src[i + 0] & 0xff;
|
||||||
|
b = src[i + 1] & 0xff;
|
||||||
|
c = src[i + 2] & 0xff;
|
||||||
|
|
||||||
c = bitbuf[0] >> 2;
|
dst[k + 0] = table[a >> 2];
|
||||||
assert(c < 64);
|
dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
|
||||||
out[j++] = base64_table[(int)c];
|
dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
|
||||||
assert(j < out_len);
|
dst[k + 3] = table[c & 0x3f];
|
||||||
|
|
||||||
c = ((bitbuf[0] & 0x03) << 4) | (bitbuf[1] >> 4);
|
i += 3;
|
||||||
assert(c < 64);
|
k += 4;
|
||||||
out[j++] = base64_table[(int)c];
|
|
||||||
assert(j < out_len);
|
|
||||||
|
|
||||||
if (b1_oob) {
|
|
||||||
out[j++] = '=';
|
|
||||||
} else {
|
|
||||||
c = ((bitbuf[1] & 0x0F) << 2) | (bitbuf[2] >> 6);
|
|
||||||
assert(c < 64);
|
|
||||||
out[j++] = base64_table[(int)c];
|
|
||||||
}
|
|
||||||
assert(j < out_len);
|
|
||||||
|
|
||||||
if (b2_oob) {
|
|
||||||
out[j++] = '=';
|
|
||||||
} else {
|
|
||||||
c = bitbuf[2] & 0x3F;
|
|
||||||
assert(c < 64);
|
|
||||||
out[j++] = base64_table[(int)c];
|
|
||||||
}
|
|
||||||
assert(j <= out_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Local<String> string = String::New(out, out_len);
|
if (n != slen) {
|
||||||
delete [] out;
|
switch (slen - n) {
|
||||||
|
case 1:
|
||||||
|
a = src[i + 0] & 0xff;
|
||||||
|
dst[k + 0] = table[a >> 2];
|
||||||
|
dst[k + 1] = table[(a & 3) << 4];
|
||||||
|
dst[k + 2] = '=';
|
||||||
|
dst[k + 3] = '=';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
a = src[i + 0] & 0xff;
|
||||||
|
b = src[i + 1] & 0xff;
|
||||||
|
dst[k + 0] = table[a >> 2];
|
||||||
|
dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
|
||||||
|
dst[k + 2] = table[(b & 0x0f) << 2];
|
||||||
|
dst[k + 3] = '=';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Local<String> string = String::New(dst, dlen);
|
||||||
|
delete [] dst;
|
||||||
|
|
||||||
return scope.Close(string);
|
return scope.Close(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user