XPerf
LanguagesArkTSEvidence

at-includes-hot — includes/indexOf in loop (Node proxy)

Status: measured (node-proxy)

Claim

Array.includes over a 256-entry list inside a hot loop is much slower than Set.has on Node/V8 (~29×). Short-alphabet String.indexOf vs Map.get was ~0.95× (Map often loses); a dense LUT wins (~3× on L=64). Lint message (2026-10-22): Array→Set; String.indexOf→LUT — do not push Map for short haystacks.

How measured

  • Harness: examples/bench/evidence_at004_at005.js

  • Deep-dive (LUT arm): separate script, not shipped in this repo

  • runtime: node-proxy — not ArkTS VM

  • Pairs: includes→Set (N=5e4); indexOf→Map (N=2e5, alphabet len 64); LUT arm in deep-dive

  • Raw lines: at-includes-hot.jsonl

Runtime (this evidence file)

FieldValue
When2026-10-22 Asia/Shanghai (JSONL ts is UTC)
runtimenode-proxy
nodev20.19.2
v811.3.244.8-node.38
Median before (includes_loop)~13.37 ms
Median after (set_has)~0.4637 ms
ratio before/after~28.8×
Median before (indexOf_loop)~1.954 ms
Median after (map_lookup)~2.056 ms
ratio before/after~0.951×

Lint mapping

arktsperf-lint at-includes-hot: severity stays hint. JSONL is Node proxy, not device — non-escalatable alone. Fixture arktsperf-lint/fixtures/good/at-includes-hot_string_lut.ts documents the String path.

Limits

  • Primary claim is includes→Set. indexOf→Map is not a win on short alphabets; prefer LUT.
  • Default stays hint; Node proxy alone does not escalate to error.

Landed 2026-10-22

Matcher message narrowed; LUT good fixture added. Severity unchanged.

Memory (2026-10-22, node-proxy)

heapUsed delta for out array ~1.25–1.43 MiB; Set(256) alone ~184 KiB. Smell is CPU (includes→Set), not RAM reduction. at-includes-hot.mem.jsonl.