Why is numeric property access 100x slower?

Viewed 103

During testing a memory mapped vector wrapper class, it became obvious that the same property accessor code attached to numeric properties is at least 100x slower than if attached to non-numeric properties:

class Vec2 {
    constructor(buf, off) {
        this.buf = new Float32Array(buf, off, 2);
    }
    get x() {
        return this.buf[0];
    }
    get y() {
        return this.buf[1];
    }
    set x(x) {
        this.buf[0] = x;
    }
    set y(y) {
        this.buf[1] = y;
    }
    get "0"() {
        return this.buf[0];
    }
    get "1"() {
        return this.buf[1];
    }
    set "0"(x) {
        this.buf[0] = x;
    }
    set "1"(y) {
        this.buf[1] = y;
    }
}
const bench = require("@thi.ng/bench").bench;
const tx = require("@thi.ng/transducers");

const N = 10000;
const buf = new Float32Array(N * 2).fill(1);
const pts = [...tx.map((i) => new Vec2(buf.buffer, i * 8), tx.range(N))];

const updateXY = () => {
    for (let i = 0; i < N; i++) {
        pts[i].x += 1;
        pts[i].y += 2;
    }
};

const update01 = () => {
    for (let i = 0; i < N; i++) {
        pts[i]["0"] += 1;
        pts[i]["1"] += 2;
    }
};

bench(updateXY, 1000);
// 58ms

bench(update01, 1000);
// 6604ms

Could anyone care to explain possible reasons? For this specific case here, a possible workaround is extending the class from Float32Array, which does make a noticeable difference (both versions now ~70ms), but my question is more general...

class Vec2 extends Float32Array {
    constructor(buf, off) {
        super(buf, off, 2);
    }

    get x() {
        return this[0];
    }

    get y() {
        return this[1];
    }

    set x(x) {
        this[0] = x;
    }

    set y(y) {
        this[1] = y;
    }
}
0 Answers
Related