jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
const utf8Decoder = new TextDecoder();
const data = new Uint8Array(100_000);
for (var i = 0; i < data.length;) {
// Initialize to a repeated sequence of
// "xx€" to test both 1-byte and 3-byte
// utf8 decoding performance.
data[i++] = 120; // 'x'
data[i++] = 120; // 'x'
data[i++] = 226; // '€' byte 1
data[i++] = 130; // '€' byte 2
data[i++] = 172; // '€' byte 3
}
function DecodeUtf8(array, start, length) {
if (length === 0) return "";
if (length === 1) return String.fromCharCode(array[start]);
let codes = new Array(length);
let written = 0;
let end = start + length;
while (start < end) {
let c = array[start++];
if (c <= 0x7F) {
codes[written++] = c;
} else if (c <= 0xDF) {
let c2 = array[start++];
codes[written++] = ((c & 0x1F) << 6) | (c2 & 0x3F);
} else if (c <= 0xEF) {
let c2 = array[start++];
let c3 = array[start++];
codes[written++] = ((c & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F);
} else if (c <= 0xF7) {
let c2 = array[start++];
let c3 = array[start++];
let c4 = array[start++];
let utf32 = ((c & 0x7) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) |
(c4 & 0x3F);
utf32 -= 0x10000;
codes[written++] = 0xD800 + (utf32 >> 10);
codes[written++] = 0xDC00 + (utf32 & 0x3FF);
} else {
throw "invalid utf8";
}
}
if (written + 40 < codes.length) {
codes.length = written;
} else {
while (written < codes.length) codes.pop();
}
return String.fromCharCode.apply(null, codes);
}
function DecodeUtf8Subarray(array) {
let length = array.length;
if (length === 0) return "";
if (length === 1) return String.fromCharCode(array[0]);
let codes = new Array(length);
let start = 0;
let written = 0;
while (start < length) {
let c = array[start++];
if (c <= 0x7F) {
codes[written++] = c;
} else if (c <= 0xDF) {
let c2 = array[start++];
codes[written++] = ((c & 0x1F) << 6) | (c2 & 0x3F);
} else if (c <= 0xEF) {
let c2 = array[start++];
let c3 = array[start++];
codes[written++] = ((c & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F);
} else if (c <= 0xF7) {
let c2 = array[start++];
let c3 = array[start++];
let c4 = array[start++];
let utf32 = ((c & 0x7) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) |
(c4 & 0x3F);
utf32 -= 0x10000;
codes[written++] = 0xD800 + (utf32 >> 10);
codes[written++] = 0xDC00 + (utf32 & 0x3FF);
} else {
throw "invalid utf8";
}
}
if (written + 40 < codes.length) {
codes.length = written;
} else {
while (written < codes.length) codes.pop();
}
return String.fromCharCode.apply(null, codes);
}
Ready to run.
Test | Ops/sec | |
---|---|---|
Many small calls |
| ready |
One big call |
| ready |
Custom decoder (small calls, offset/length) |
| ready |
Custom decoder (small calls, subarrays) |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.