getAtPath traversal iteration styles (hit+miss)

Benchmark created on


Description

Benchmarks array iteration constructs in a getAtPath-like traversal (property access + early-exit). Uses hit and miss paths. sink prevents DCE.

Preparation HTML


Setup

"use strict";

const isObjectLike = (v) => v != null && (typeof v === "object" || typeof v === "function");

const buildRoot = () => {
  const users = Array.from({ length: 200 }, (_, i) => ({
    id: i,
    profile: {
      name: `user${i}`,
      tags: ["alpha", "beta", "gamma"],
      flags: { active: (i & 1) === 0, admin: (i % 17) === 0 },
      settings: { theme: i % 3 ? "dark" : "light" },
    },
  }));

  const items = Array.from({ length: 200 }, (_, i) => ({
    name: `item${i}`,
    deep: { value: i, nested: { ok: true } },
  }));

  const meta = { "some.key": { value: 9 }, "a b": 7, 'he said "hi"': 1, "it's ok": 2, "a\\b": 3 };

  const rootObject = {
    version: 1,
    env: { region: "eu-west-2", build: "local" },
    users,
    something: { items },
    meta,
    matrix: Array.from({ length: 40 }, (_, r) => Array.from({ length: 40 }, (_, c) => r * 40 + c)),
  };

  rootObject.a = { b: { c: { value: 123 } } };

  return rootObject;
};

const root = buildRoot();

const segmentsHit = ["a", "b", "c", "value"];
const segmentsMiss = ["a", "missing", "x", "y"];

// Prevent DCE
let sink = 0;

Teardown

// expose to avoid DCE across harnesses
window.__sink = sink;

Test runner

Ready to run.

Testing in
TestOps/sec
HIT - index for
let v = root;
for (let i = 0; i < segmentsHit.length; i++) { if (!isObjectLike(v)) break; v = v[segmentsHit[i]]; }
sink ^= v?.value ?? 0;
ready
HIT - while
let v = root, i = 0;
while (i < segmentsHit.length) { if (!isObjectLike(v)) break; v = v[segmentsHit[i++]]; }
sink ^= v?.value ?? 0;
ready
HIT - for..of
let v = root;
for (const s of segmentsHit) { if (!isObjectLike(v)) break; v = v[s]; }
sink ^= v?.value ?? 0;
ready
HIT - forEach (flag)
let v = root, dead = false;
segmentsHit.forEach((s) => { if (dead) return; if (!isObjectLike(v)) return void (dead = true); v = v[s]; });
sink ^= v?.value ?? 0;
ready
HIT - reduce
const v = segmentsHit.reduce((acc, s) => (isObjectLike(acc) ? acc[s] : undefined), root);
sink ^= v?.value ?? 0;
ready
MISS - index for
let v = root;
for (let i = 0; i < segmentsMiss.length; i++) { if (!isObjectLike(v)) break; v = v[segmentsMiss[i]]; }
sink ^= v ?? 0;
ready
MISS - while
let v = root, i = 0;
while (i < segmentsMiss.length) { if (!isObjectLike(v)) break; v = v[segmentsMiss[i++]]; }
sink ^= v ?? 0;
ready
MISS - for..of
let v = root;
for (const s of segmentsMiss) { if (!isObjectLike(v)) break; v = v[s]; }
sink ^= v ?? 0;
ready
MISS - reduce
const v = segmentsMiss.reduce((acc, s) => (isObjectLike(acc) ? acc[s] : undefined), root);
sink ^= v ?? 0;
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.