function get1024Bytes(n) {
const bytes = new Uint8Array(n * 1024);
for (let i = 0; i < bytes.length; i += 1) {
bytes[i] = Math.random() * 0xff;
}
return bytes;
}
const bytes = get1024Bytes(128);
const utf16decoder = new TextDecoder('utf-16');
// An example result:
// const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
return Array.from(bytes, (byte) =>
String.fromCodePoint(byte),
).join("");
return Array.from(bytes, (byte) =>
String.fromCharCode(byte),
).join("");
return bytes.reduce((s, byte) => s + String.fromCodePoint(byte), "");
return bytes.reduce((s, byte) => s + String.fromCharCode(byte), "");
let s = '';
for (const byte of bytes) {
s += String.fromCodePoint(byte);
}
return s;
let s = '';
for (const byte of bytes) {
s += String.fromCharCode(byte);
}
return s;
const QUANTUM = 32768;
const chunks = [];
for (let i = 0; i < bytes.length; i += QUANTUM) {
chunks.push(bytes.slice(i, i + QUANTUM));
}
return chunks.reduce((s, i) => s + String.fromCodePoint.apply(null, i), '');
const QUANTUM = 32768;
const chunks = [];
for (let i = 0; i < bytes.length; i += QUANTUM) {
chunks.push(bytes.slice(i, i + QUANTUM));
}
return chunks.reduce((s, i) => s + String.fromCharCode.apply(null, i), '');
const QUANTUM = 32768;
let s = '';
for (let i = 0; i < bytes.length; i += QUANTUM) {
s += String.fromCodePoint.apply(null, bytes.slice(i, i + QUANTUM));
}
return s;
const QUANTUM = 32768;
let s = '';
for (let i = 0; i < bytes.length; i += QUANTUM) {
s += String.fromCharCode.apply(null, bytes.slice(i, i + QUANTUM));
}
return s;
const QUANTUM = 128;
const chunks = [];
for (let i = 0; i < bytes.length; i += QUANTUM) {
chunks.push(bytes.slice(i, i + QUANTUM));
}
return chunks.reduce((s, i) => s + String.fromCodePoint.apply(null, i), '');
const QUANTUM = 128;
const chunks = [];
for (let i = 0; i < bytes.length; i += QUANTUM) {
chunks.push(bytes.slice(i, i + QUANTUM));
}
return chunks.reduce((s, i) => s + String.fromCharCode.apply(null, i), '');
const QUANTUM = 128;
let s = '';
for (let i = 0; i < bytes.length; i += QUANTUM) {
s += String.fromCodePoint.apply(null, bytes.slice(i, i + QUANTUM));
}
return s;
const QUANTUM = 128;
let s = '';
for (let i = 0; i < bytes.length; i += QUANTUM) {
s += String.fromCharCode.apply(null, bytes.slice(i, i + QUANTUM));
}
return s;
return utf16decoder.decode(new Uint16Array(bytes));
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
Array.from + join + fromCodePoint | |
Array.from + join + fromCharCode | |
Array.reduce + fromCodePoint | |
Array.reduce + fromCharCode | |
String concatenation + fromCodePoint | |
String concatenation + fromCharCode | |
Function.apply + Array.reduce+ fromCodePoint (chunked) | |
Function.apply + Array.reduce + fromCharCode (chunked) | |
Function.apply + String concatenation + fromCodePoint (chunked) | |
Function.apply + String concatenation + fromCharCode (chunked) | |
Function.apply + Array.reduce+ fromCodePoint (small chunks) | |
Function.apply + Array.reduce + fromCharCode (small chunks) | |
Function.apply + String concatenation + fromCodePoint (small chunks) | |
Function.apply + String concatenation + fromCharCode (small chunks) | |
utf-16 TextDecoder |
Test name | Executions per second |
---|---|
Array.from + join + fromCodePoint | 272.6 Ops/sec |
Array.from + join + fromCharCode | 274.9 Ops/sec |
Array.reduce + fromCodePoint | 1155.3 Ops/sec |
Array.reduce + fromCharCode | 1122.5 Ops/sec |
String concatenation + fromCodePoint | 1423.8 Ops/sec |
String concatenation + fromCharCode | 1434.4 Ops/sec |
Function.apply + Array.reduce+ fromCodePoint (chunked) | 532.2 Ops/sec |
Function.apply + Array.reduce + fromCharCode (chunked) | 1485.3 Ops/sec |
Function.apply + String concatenation + fromCodePoint (chunked) | 828.0 Ops/sec |
Function.apply + String concatenation + fromCharCode (chunked) | 1661.4 Ops/sec |
Function.apply + Array.reduce+ fromCodePoint (small chunks) | 786.5 Ops/sec |
Function.apply + Array.reduce + fromCharCode (small chunks) | 1554.6 Ops/sec |
Function.apply + String concatenation + fromCodePoint (small chunks) | 774.1 Ops/sec |
Function.apply + String concatenation + fromCharCode (small chunks) | 1601.5 Ops/sec |
utf-16 TextDecoder | 4179.2 Ops/sec |
The benchmark tests various methods for converting a byte array into a binary string in JavaScript. These approaches primarily differ in their use of string conversion functions, array manipulation methods, and how they handle large data through chunking.
Conversion Techniques:
Uint8Array
) into a binary string using either String.fromCodePoint
or String.fromCharCode
.Implementation Variations:
Array.from
with join
.Array.prototype.reduce
.for...of
loops for string concatenation.TextDecoder (utf-16):
TextDecoder
class is tested specifically for its efficiency in decoding a Uint16Array
from the byte input, which offers a contrast to manually converting strings.Array.from with String.fromCodePoint
and String.fromCharCode
:
Array.reduce:
reduce
function to accumulate a string by applying a conversion function.String Concatenation with for...of
:
Chunking Methods:
Function.apply
. This method reduces the size of each function call by grouping bytes.TextDecoder with Uint16Array
:
TextDecoder
API for converting bytes to text, leveraging built-in browser capabilities.TextDecoder
, which may not be supported in all environments or may not be as flexible as manual methods for certain types of encoding.Aside from the methods listed above, alternatives could include:
Buffer
in Node.js for byte manipulation and conversions, especially if the focus is on server-side applications.base64-js
for base64 operations or pako
for compression tasks.Overall, understanding these benchmarks provides valuable insights into optimizing text encoding conversion in JavaScript.