class CustomArray extends Array {
constructor(args) {
super(args);
this.position = 0;
}
}
class CustomUint8Array extends Uint8Array {
constructor(args) {
super(args);
this.position = 0;
}
}
const LENGTH = 12000;
var rArray = [];
var uint8Array = new Uint8Array(LENGTH);
var uint8ArrayExp = new Uint8Array(LENGTH);
uint8ArrayExp.position = 0;
var cArray = new CustomArray(LENGTH);
var cUint8Array = new CustomUint8Array(LENGTH);
for (let i = 0; i < LENGTH; i++) {
const v = ~~(Math.random() * 255);
rArray.push(v);
uint8Array[i] = v;
uint8ArrayExp[i] = v;
cArray[i] = v;
cUint8Array[i] = v;
}
console.log(`rArray: ${rArray.length}, uint8Array: ${uint8Array.length}, uint8ArrayExp: ${uint8ArrayExp.length}, cArray: ${cArray.length}, cUint8Array: ${cUint8Array.length}`);
function read(arr, offset) {
let pos = offset;
while (pos < arr.length) {
pos++;
if (arr[pos] < 127) {
return pos;
}
}
return pos;
}
let o = 0;
while (o < rArray.length) {
o = read(rArray, o);
}
function read(arr, offset) {
let pos = offset;
while (pos < arr.length) {
pos++;
if (arr[pos] < 127) {
return pos;
}
}
return pos;
}
let o = 0;
while (o < uint8Array.length) {
o = read(uint8Array, o);
}
function read(arr) {
while (arr.position < arr.length) {
arr.position++;
if (arr[arr.position] < 127) {
return arr.position;
}
}
return arr.position;
}
let o = 0;
uint8ArrayExp.position = 0;
while (o < uint8ArrayExp.length) {
o = read(uint8ArrayExp);
}
function read(arr) {
while (arr.position < arr.length) {
arr.position++;
if (arr[arr.position] < 127) {
return arr.position;
}
}
return arr.position;
}
let o = 0;
while (o < cArray.length) {
o = read(cArray);
}
function read(arr) {
while (arr.position < arr.length) {
arr.position++;
if (arr[arr.position] < 127) {
return arr.position++;
}
}
return arr.position;
}
let o = 0;
while (o < cUint8Array.length) {
o = read(cUint8Array, o);
}
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
Regular Array | |
Uint Array | |
Uint Array Expando | |
Custom Array | |
Custom Uint Array |
Test name | Executions per second |
---|---|
Regular Array | 4723.9 Ops/sec |
Uint Array | 5164.0 Ops/sec |
Uint Array Expando | 5110.8 Ops/sec |
Custom Array | 50820496.0 Ops/sec |
Custom Uint Array | 44522384.0 Ops/sec |
Let's break down the benchmark and its various components.
Benchmark Definition
The benchmark is designed to test how extending an ArrayBufferView
(such as Uint8Array
) with custom properties or functionality affects performance. Specifically, it creates three types of arrays:
Array
)Uint8Array
)CustomUint8Array
, which extends Uint8Array
)Each array has a similar constructor and initialization process, but the key difference lies in how they access elements and perform operations.
Options Compared
The benchmark compares the performance of three different approaches:
arr[pos]
) to access elements.position
property to keep track of the current index, but still uses standard array indexing syntax (arr[pos]
) to access elements.Uint8Array
with a custom position
property that increments and accesses elements using the same syntax as the regular array (arr[arr.position]
). However, it also has an additional increment operation after returning the position.Pros and Cons of Different Approaches
Uint8Array
.position
property.Uint8Array
with custom indexing syntax, potentially reducing overhead.position
property and additional operations.Benchmark Results
The latest benchmark results show that:
CustomUint8Array
) has the highest performance (508 MB/s) among all three options.Uint8Array
) is close behind, with a slightly lower performance (445 MB/s).Array
) performs the worst, likely due to slower access times.Conclusion
The benchmark suggests that extending an ArrayBufferView
with custom properties or functionality can lead to improved performance, especially when compared to using standard array indexing syntax. However, the added complexity of managing indices and incrementing/resetting positions may outweigh any benefits for some use cases.