Script Preparation code:
x
 
var bench1buffer;
var bench2buffer;
var bench3buffer;
var size = 1_000_000;
{
    const stride = 10;
    bench1buffer = new ArrayBuffer(stride * size);
    /*
      0 u16 id
      2 f32 x
      6 f32 y
    */
    for (let i = 0; i < size; i++) {
        const struct = new DataView(bench1buffer, i * stride, stride);
        struct.setUint16(0, i, true);
        struct.setFloat32(2, i, true);
        struct.setFloat32(6, i * 2, true);
    }
}
{
    const stride = 12;
    bench2buffer = new ArrayBuffer(stride * size);
    /*
      0 u16 id
      4 f32 x
      8 f32 y
    */
    for (let i = 0; i < size; i++) {
        const struct = new DataView(bench2buffer, i * stride, stride);
        struct.setUint16(0, i, true);
        struct.setFloat32(4, i, true);
        struct.setFloat32(8, i * 2, true);
    }
}
{
    bench3buffer = {
        id: new Uint16Array(size),
        x: new Float32Array(size),
        y: new Float32Array(size),
    };
    for (let i = 0; i < size; i++) {
        bench3buffer.id[i] = i;
        bench3buffer.x[i] = i;
        bench3buffer.y[i] = i * 2;
    }
}
Tests:
  • DataView AoS

     
    const stride = 10;
    /*
      0 u16 id
      2 f32 x
      6 f32 y
    */
    let sum = 0;
    for (let i = 0; i < size; i++) {
      const struct = new DataView(bench1buffer, i * stride, stride);
      const id = struct.getUint16(0, true);
      const x = struct.getFloat32(2, true);
      const y = struct.getFloat32(6, true);
      sum += id + x * y;
    }
    console.log(1, sum);
  • DataView byte-aligned AoS

     
    const stride = 12;
    /*
      0 u16 id
      4 f32 x
      8 f32 y
    */
    let sum = 0;
    for (let i = 0; i < size; i++) {
      const struct = new DataView(bench2buffer, i * stride, stride);
      const id = struct.getUint16(0, true);
      const x = struct.getFloat32(4, true);
      const y = struct.getFloat32(8, true);
      sum += id + x * y;
    }
    console.log(2, sum);
  • TypedArray byte-aligned AoS

     
    const stride = 12;
    /*
      0 u16 id
      4 f32 x
      8 f32 y
    */
    const f32s = new Float32Array(bench2buffer);
    const u16s = new Uint16Array(bench2buffer);
    let sum = 0;
    for (let i = 0; i < size; i++) {
      const offset = i * stride;
      const id = u16s[offset / 2];
      const x = f32s[offset / 4 + 1];
      const y = f32s[offset / 4 + 2];
      sum += id + x * y;
    }
    console.log(3, sum);
  • TypeArray SoA

     
    let sum = 0;
    const idbuf = bench3buffer.id;
    const xbuf = bench3buffer.x;
    const ybuf = bench3buffer.y;
    for (let i = 0; i < size; i++) {
      const id = idbuf[i];
      const x = xbuf[i];
      const y = ybuf[i];
      sum += id + x * y;
    }
    console.log(3, sum);
Rendered benchmark preparation results:

Suite status: <idle, ready to run>

Previous results

Experimental features:

  • Test case name Result
    DataView AoS
    DataView byte-aligned AoS
    TypedArray byte-aligned AoS
    TypeArray SoA

    Fastest: N/A

    Slowest: N/A

Latest run results:
Run details: (Test run date: 3 years ago)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Chrome 98 on Windows
View result in a separate tab
Test name Executions per second
DataView AoS 3.0 Ops/sec
DataView byte-aligned AoS 3.0 Ops/sec
TypedArray byte-aligned AoS 14.9 Ops/sec
TypeArray SoA 14.9 Ops/sec