remove unnecessary data structs Dict+MapArray

This commit is contained in:
Schluffe
2026-08-27 23:43:28 +02:00
parent 2f7957b28a
commit 7b3c9865fe
10 changed files with 12 additions and 466 deletions
-22
View File
@@ -1,22 +0,0 @@
structure,size,latency_ns_avg,latency_ns_med
MapArray,100,0.03,0.03
Dictionary,100,0.00,0.00
Map,100,0.00,0.00
MapArray,250,0.05,0.05
Dictionary,250,0.00,0.00
Map,250,0.00,0.00
MapArray,500,0.09,0.09
Dictionary,500,0.00,0.00
Map,500,0.00,0.00
MapArray,999,0.16,0.16
Dictionary,999,0.01,0.00
Map,999,0.00,0.00
MapArray,2500,0.42,0.42
Dictionary,2500,0.01,0.01
Map,2500,0.01,0.01
MapArray,5000,0.81,0.80
Dictionary,5000,0.02,0.02
Map,5000,0.01,0.01
MapArray,10000,1.66,1.66
Dictionary,10000,0.05,0.04
Map,10000,0.02,0.02
1 structure size latency_ns_avg latency_ns_med
2 MapArray 100 0.03 0.03
3 Dictionary 100 0.00 0.00
4 Map 100 0.00 0.00
5 MapArray 250 0.05 0.05
6 Dictionary 250 0.00 0.00
7 Map 250 0.00 0.00
8 MapArray 500 0.09 0.09
9 Dictionary 500 0.00 0.00
10 Map 500 0.00 0.00
11 MapArray 999 0.16 0.16
12 Dictionary 999 0.01 0.00
13 Map 999 0.00 0.00
14 MapArray 2500 0.42 0.42
15 Dictionary 2500 0.01 0.01
16 Map 2500 0.01 0.01
17 MapArray 5000 0.81 0.80
18 Dictionary 5000 0.02 0.02
19 Map 5000 0.01 0.01
20 MapArray 10000 1.66 1.66
21 Dictionary 10000 0.05 0.04
22 Map 10000 0.02 0.02
-89
View File
@@ -1,89 +0,0 @@
// bench/churn-sweep.ts
import { Bench } from "tinybench";
import { type Box, box } from "../engine/lib/box.ts";
import {
createDictionary,
deleteEntry,
setEntry,
} from "../engine/lib/Dictionary.ts";
import MapArray from "../engine/lib/MapArray.ts";
const SIZES = [100, 250, 500, 999, 2500, 5000, 10000];
const CHURN_N = 100;
const churnKeys = Array.from({ length: CHURN_N }, (_, i) => `churn-${i}`);
let sink = 0;
function makeBaseData(size: number): Array<[string, Box<number>]> {
const data: Array<[string, Box<number>]> = [];
let i = size;
while (i-- > 0) data.push([String(i), box(i)]);
return data;
}
type Row = {
structure: string;
size: number;
latencyNsAvg: number;
latencyNsMed: number;
};
const rows: Row[] = [];
for (const size of SIZES) {
const baseData = makeBaseData(size);
const ma = new MapArray(structuredClone(baseData));
const dict = createDictionary(structuredClone(baseData));
const map = new Map(structuredClone(baseData));
const bench = new Bench({ name: `churn @ size=${size}`, time: 500 });
bench
.add("MapArray", () => {
for (const key of churnKeys) ma.set(key, box(1));
for (const key of churnKeys) ma.delete(key);
sink += ma.entries().length;
})
.add("Dictionary", () => {
for (const key of churnKeys) setEntry(dict, [key, box(1)]);
for (const key of churnKeys) deleteEntry(dict, key);
sink += dict.entries.length;
})
.add("Map", () => {
for (const key of churnKeys) map.set(key, box(1));
for (const key of churnKeys) map.delete(key);
sink += map.size;
});
await bench.run();
for (const task of bench.tasks) {
const res = task.result;
if (!res) continue;
rows.push({
structure: task.name,
size,
latencyNsAvg: res.latency.mean,
latencyNsMed: res.latency.p50 ?? res.latency.mean,
});
}
console.log(`-- size=${size} done --`);
console.table(bench.table());
}
// CSV output
const header = "structure,size,latency_ns_avg,latency_ns_med";
const csvLines = rows.map(
(r) =>
`${r.structure},${r.size},${r.latencyNsAvg.toFixed(2)},${r.latencyNsMed.toFixed(2)}`,
);
const csv = [header, ...csvLines].join("\n");
(await Deno.writeTextFile?.("churn-sweep.csv", csv)) ??
(await import("node:fs/promises")).then((fs) =>
fs.writeFile("churn-sweep.csv", csv),
);
console.log("\nWrote churn-sweep.csv");
console.log("sink (ignore):", sink);
-77
View File
@@ -1,77 +0,0 @@
// bench/churn.ts
import { Bench } from "tinybench";
import { type Box, box } from "./../engine/lib/box.ts";
import {
createDictionary,
deleteEntry,
getEntry,
setEntry,
} from "./../engine/lib/Dictionary.ts";
import MapArray from "./../engine/lib/MapArray.ts";
const bench = new Bench({ name: "churn", time: 1000 });
const SIZE = 999;
const baseData: Array<[string, Box<number>]> = [];
{
let i = SIZE;
while (i-- > 0) baseData.push([String(i), box(i)]);
}
// Churn keys: a rotating window of "new" entities not in the base set,
// so every set/delete pair actually does real insert+remove work
// rather than repeatedly hitting the same already-resident key.
const CHURN_N = 100;
const churnKeys = Array.from({ length: CHURN_N }, (_, i) => `churn-${i}`);
let sink = 0; // anti-DCE: something observable reads this later
function freshMapArray() {
return new MapArray(structuredClone(baseData));
}
function freshDictionary() {
return createDictionary(structuredClone(baseData));
}
function freshMap() {
return new Map(structuredClone(baseData));
}
// Each task rebuilds nothing per-iteration except doing insert+remove
// on a fixed churn window against a persistent SIZE-element base structure —
// this mirrors "N entities steady-state, M entering/leaving per frame".
const ma = freshMapArray();
const dict = freshDictionary();
const map = freshMap();
bench
.add("MapArray churn (set+delete)", () => {
for (const key of churnKeys) {
ma.set(key, box(1));
}
for (const key of churnKeys) {
ma.delete(key);
}
sink += ma.entries().length;
})
.add("Dictionary churn (set+delete)", () => {
for (const key of churnKeys) {
setEntry(dict, [key, box(1)]);
}
for (const key of churnKeys) {
deleteEntry(dict, key);
}
sink += dict.entries.length;
})
.add("Map churn (set+delete)", () => {
for (const key of churnKeys) {
map.set(key, box(1));
}
for (const key of churnKeys) {
map.delete(key);
}
sink += map.size;
});
await bench.run();
console.table(bench.table());
console.log("sink (ignore):", sink);
+4 -46
View File
@@ -1,53 +1,11 @@
import { Bench } from "tinybench";
import { type Box, box } from "./../engine/lib/box.ts";
import {
createDictionary,
forEntry,
getEntry,
} from "./../engine/lib/Dictionary.ts";
import MapArray from "./../engine/lib/MapArray.ts";
const bench = new Bench({ name: "MapArray get", time: 3000 });
const bench = new Bench({ name: "", time: 1000 });
let sink = 0;
const testData: Array<[string, Box<number>]> = [];
let i = 999;
while (i-- > 0) {
testData.push([String(i), box(i)]);
}
const ma = new MapArray(structuredClone(testData));
const dict = createDictionary(structuredClone(testData));
const map = new Map(structuredClone(testData));
bench
.add("MapArray iter/get reads", () => {
let sum = 0;
for (const [key] of ma.entries()) {
sum += ma.get(key)!.value;
}
sink += sum;
})
.add("Dictionary iter/get reads", () => {
let sum = 0;
forEntry(dict, (_, key) => {
sum += getEntry(dict, key)!.value;
});
sink += sum;
})
.add("Map iter/get reads", () => {
let sum = 0;
for (const [key] of map.entries()) {
sum += map.get(key)!.value;
}
sink += sum;
});
bench.add("", () => {
sink += 1;
});
await bench.run();