Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
5ac719d
doc: add deprecations page to docs toc
targos Apr 7, 2017
1ee38eb
util: add %i and %f formatting specifiers
silverwind Dec 16, 2016
6130d54
deps: backport 8dde6ac from upstream V8
danbev Mar 27, 2017
fdf76d5
tools: add missing #include "unicode/putil.h"
srl295 Mar 27, 2017
87ca9a6
test: fix flaky child-process-exec-kill-throws
Trott Mar 29, 2017
8823861
tools: update dotfile whitelist in .gitignore
targos Mar 29, 2017
ffbcfdf
src: fix base64 decoding
seishun Mar 22, 2017
2f88de1
vm: use SetterCallback to set func declarations
AnnaMag Mar 26, 2017
305f822
net: rename internal functions for readability
joyeecheung Mar 11, 2017
b5283f9
doc: add logo to README
silverwind Mar 31, 2017
6ccbf38
test: synchronize WPT url setter test data
watilde Apr 3, 2017
b52b3f6
test: reduce buffer size in buffer-creation test
thefourtheye Feb 5, 2017
3af9101
doc, inspector: note that the host is optional
gibfahn Mar 28, 2017
72a27b3
build: use $(RM) in Makefile for consistency
gibfahn Apr 1, 2017
b15dc95
test: fix flaky test-child-process-exec-timeout
santigimeno Apr 1, 2017
f057cc3
benchmark: replace [].join() with ''.repeat()
vsemozhetbyt Apr 2, 2017
d6e9cf7
doc: fix and update examples in http.md
vsemozhetbyt Apr 2, 2017
fb34d9c
test: increase querystring coverage
davidtaikocha Apr 2, 2017
805ebef
buffer: optimize decoding wrapped base64 data
aqrln Mar 31, 2017
9e6b0a4
test: performance, remove Popen(shell=True) on Win
refack Mar 30, 2017
36617fd
doc: add notes to http.get options
raphaelokon Mar 29, 2017
731a200
doc: update Mac OS X references in releases.md
Mar 29, 2017
8058bae
tools: update ESLint to 3.19.0
Trott Apr 2, 2017
c814c7e
events: do not keep arrays with a single listener
lpinca Mar 25, 2017
806c4f3
doc: fix fs.read arg type
darai0512 Mar 26, 2017
cf1117b
doc: fix the timing of setImmediate's execution
darai0512 Mar 26, 2017
6083e7a
benchmark: avoid TurboFan deopt in arrays bench
targos Mar 17, 2017
a11ed6a
test: more robust check for location of `node.exe`
refack Mar 29, 2017
961c89c
doc: add table of contents to README.md
Minimalistic Mar 1, 2017
8caf6fd
test: add Unicode characters regression test
aqrln Feb 16, 2017
4b54520
test: refactor mkdtemp test and added async
lucamaraschi Mar 27, 2017
74d0266
doc: fix string interpolation in Stream 'finish'
vhmth Apr 4, 2017
f60b455
doc: modernize and fix code examples in https.md
vsemozhetbyt Apr 2, 2017
b495b6a
build: make configure print statements consistent
danbev Apr 3, 2017
a703bde
build: add checks for openssl configure options
danbev Apr 3, 2017
6feea08
buffer: preallocate array with buffer length
alemures Mar 7, 2017
d641164
doc: update pull request template URL layout
Trott Apr 4, 2017
a735c16
deps: backport ec1ffe3 from upstream V8
danbev Mar 27, 2017
d4d6986
build: fix path voodoo in icu-generic.gyp
refack Mar 30, 2017
3cdd04b
test: skip irrelevant test on Windows
Trott Apr 6, 2017
ac200a6
test: add a second argument to assert.throws()
dave-k Mar 30, 2017
2fb2289
doc: add sub domain to host in url
styfle Apr 5, 2017
83f855d
doc: add aqrln to collaborators
aqrln Apr 7, 2017
c0b7c07
doc: add refack to collaborators
refack Apr 7, 2017
376f5ef
doc: document the performance team
gibfahn Apr 4, 2017
3e8991c
doc: modernize and fix code examples in modules.md
vsemozhetbyt Apr 5, 2017
4a6bb37
doc: fix confusing reference in net.md
vsemozhetbyt Apr 5, 2017
6826637
doc: fix missing argument for dns.resolvePtr()
uppinder Apr 7, 2017
0f4319a
src: use std::string for trace enabled_categories
sam-github Apr 5, 2017
2f9e2fc
doc: update information on test/known_issues
Apr 6, 2017
37568c0
src: use std::list for at_exit_functions
danbev Apr 6, 2017
3b765f5
doc: fix confusing example in process.md
vsemozhetbyt Apr 8, 2017
67d2114
crypto: handle exceptions in hmac/hash.digest
tniessen Apr 2, 2017
c11c23b
doc: make the heading consistent
thefourtheye Feb 26, 2017
b997e62
test: add internal/socket_list tests
davidtaikocha Mar 29, 2017
77353b3
tools: ignore URLs in line length linting
Trott Mar 17, 2017
211dd16
benchmark: add final clean-up to module-loader.js
vsemozhetbyt Mar 19, 2017
9f73df5
deps: cherry-pick 22858cb from V8 upstream
ofrobots Mar 23, 2017
0794478
2017-04-11, Version 7.9.0 (Current)
Apr 11, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
buffer: optimize decoding wrapped base64 data
The fast base64 decoder used to switch to the slow one permanently when
it saw a whitespace or other garbage character.  Since the most common
situation such characters may be encountered in is line-wrapped base64
data, a more profitable strategy is to decode a single 24-bit group with
the slow decoder and then continue running the fast algorithm.

PR-URL: #12146
Ref: #12114
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
aqrln authored and Italo A. Casas committed Apr 10, 2017
commit 805ebef8b160b7fd3c003ba7e30aec8f92fea67f
26 changes: 26 additions & 0 deletions benchmark/buffers/buffer-base64-decode-wrapped.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

const common = require('../common.js');

const bench = common.createBenchmark(main, {
n: [32],
});

function main(conf) {
const n = +conf.n;
const charsPerLine = 76;
const linesCount = 8 << 16;
const bytesCount = charsPerLine * linesCount / 4 * 3;

const line = 'abcd'.repeat(charsPerLine / 4) + '\n';
const data = line.repeat(linesCount);
// eslint-disable-next-line no-unescaped-regexp-dot
data.match(/./); // Flatten the string
const buffer = Buffer.alloc(bytesCount, line, 'base64');

bench.start();
for (var i = 0; i < n; i++) {
buffer.base64Write(data, 0, bytesCount);
}
bench.end(n);
}
69 changes: 35 additions & 34 deletions src/base64.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,36 +52,33 @@ extern const int8_t unbase64_table[256];


template <typename TypeName>
size_t base64_decode_slow(char* dst, size_t dstlen,
const TypeName* src, size_t srclen) {
bool base64_decode_group_slow(char* const dst, const size_t dstlen,
const TypeName* const src, const size_t srclen,
size_t* const i, size_t* const k) {
uint8_t hi;
uint8_t lo;
size_t i = 0;
size_t k = 0;
for (;;) {
#define V(expr) \
for (;;) { \
const uint8_t c = src[i]; \
lo = unbase64(c); \
i += 1; \
if (lo < 64) \
break; /* Legal character. */ \
if (c == '=' || i >= srclen) \
return k; \
} \
expr; \
if (i >= srclen) \
return k; \
if (k >= dstlen) \
return k; \
hi = lo;
V(/* Nothing. */);
V(dst[k++] = ((hi & 0x3F) << 2) | ((lo & 0x30) >> 4));
V(dst[k++] = ((hi & 0x0F) << 4) | ((lo & 0x3C) >> 2));
V(dst[k++] = ((hi & 0x03) << 6) | ((lo & 0x3F) >> 0));
for (;;) { \
const uint8_t c = src[*i]; \
lo = unbase64(c); \
*i += 1; \
if (lo < 64) \
break; /* Legal character. */ \
if (c == '=' || *i >= srclen) \
return false; /* Stop decoding. */ \
} \
expr; \
if (*i >= srclen) \
return false; \
if (*k >= dstlen) \
return false; \
hi = lo;
V(/* Nothing. */);
V(dst[(*k)++] = ((hi & 0x3F) << 2) | ((lo & 0x30) >> 4));
V(dst[(*k)++] = ((hi & 0x0F) << 4) | ((lo & 0x3C) >> 2));
V(dst[(*k)++] = ((hi & 0x03) << 6) | ((lo & 0x3F) >> 0));
#undef V
}
UNREACHABLE();
return true; // Continue decoding.
}


Expand All @@ -90,8 +87,8 @@ size_t base64_decode_fast(char* const dst, const size_t dstlen,
const TypeName* const src, const size_t srclen,
const size_t decoded_size) {
const size_t available = dstlen < decoded_size ? dstlen : decoded_size;
const size_t max_i = srclen / 4 * 4;
const size_t max_k = available / 3 * 3;
size_t max_i = srclen / 4 * 4;
size_t i = 0;
size_t k = 0;
while (i < max_i && k < max_k) {
Expand All @@ -102,16 +99,20 @@ size_t base64_decode_fast(char* const dst, const size_t dstlen,
unbase64(src[i + 3]);
// If MSB is set, input contains whitespace or is not valid base64.
if (v & 0x80808080) {
break;
const size_t old_i = i;
if (!base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k))
return k;
max_i = old_i + (srclen - i) / 4 * 4; // Align max_i again.
} else {
dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03);
dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F);
dst[k + 2] = ((v >> 2) & 0xC0) | ((v >> 0) & 0x3F);
i += 4;
k += 3;
}
dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03);
dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F);
dst[k + 2] = ((v >> 2) & 0xC0) | ((v >> 0) & 0x3F);
i += 4;
k += 3;
}
if (i < srclen && k < dstlen) {
return k + base64_decode_slow(dst + k, dstlen - k, src + i, srclen - i);
base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k);
}
return k;
}
Expand Down