mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
A candidate release now also runs a pass once the live cycle-headered count has grown by 4096 objects since the last pass. A dead graph is usually reachable from one candidate (its root), so the candidate count alone let a few hundred dead graphs pile up before a pass, which then walked them after they had left the cache. markGray records the objects it grays and counts the ones still externally referenced after the trial decrements. When none is, every gray object is garbage, so the pass whitens the recorded set and skips scan. markGray also records each edge it skips into an older generation, so a restricted pass pins those targets without tracing the white set a second time. Adds the cyclic-graphs runtime benchmark and corpus programs 5700 and 5701.
105 lines
3.0 KiB
TypeScript
105 lines
3.0 KiB
TypeScript
// Object graphs with back references, built and dropped: trees whose nodes
|
|
// point to their parent and siblings, rings of records that share a
|
|
// long-lived registry, and closures that capture the object that holds them.
|
|
// Dropping each graph leaves only cyclic references, so the cycle collector
|
|
// reclaims it.
|
|
|
|
class TreeNode {
|
|
parent: TreeNode | undefined = undefined;
|
|
children: TreeNode[] = [];
|
|
sibling: TreeNode | undefined = undefined;
|
|
weight: number;
|
|
constructor(weight: number) {
|
|
this.weight = weight;
|
|
}
|
|
}
|
|
|
|
function buildTree(depth: number, parent: TreeNode | undefined, weight: number): TreeNode {
|
|
const node = new TreeNode(weight);
|
|
node.parent = parent;
|
|
if (depth > 0) {
|
|
for (let i = 0; i < 3; i++) node.children.push(buildTree(depth - 1, node, weight * 3 + i));
|
|
node.children[0]!.sibling = node.children[1]!;
|
|
node.children[1]!.sibling = node.children[2]!;
|
|
node.children[2]!.sibling = node.children[0]!;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
function treeWeight(node: TreeNode): number {
|
|
let total = node.weight;
|
|
for (const child of node.children) total += treeWeight(child);
|
|
return total % 1000003;
|
|
}
|
|
|
|
class Category {
|
|
members = 0;
|
|
name: string;
|
|
constructor(name: string) {
|
|
this.name = name;
|
|
}
|
|
}
|
|
|
|
class Member {
|
|
next: Member | undefined = undefined;
|
|
category: Category;
|
|
rank: number;
|
|
constructor(category: Category, rank: number) {
|
|
this.category = category;
|
|
this.rank = rank;
|
|
category.members++;
|
|
}
|
|
}
|
|
|
|
function buildRing(categories: Category[], size: number, seed: number): Member {
|
|
const first = new Member(categories[seed % categories.length]!, seed);
|
|
let last = first;
|
|
for (let i = 1; i < size; i++) {
|
|
const member = new Member(categories[(seed + i * 7) % categories.length]!, seed + i);
|
|
last.next = member;
|
|
last = member;
|
|
}
|
|
last.next = first;
|
|
return first;
|
|
}
|
|
|
|
class Widget {
|
|
label: string;
|
|
onChange: (() => number) | undefined = undefined;
|
|
constructor(label: string) {
|
|
this.label = label;
|
|
}
|
|
}
|
|
|
|
function buildWidgets(count: number): number {
|
|
const widgets: Widget[] = [];
|
|
for (let i = 0; i < count; i++) {
|
|
const widget = new Widget(`w${i}`);
|
|
widget.onChange = () => widget.label.length + i;
|
|
widgets.push(widget);
|
|
}
|
|
let total = 0;
|
|
for (const widget of widgets) total += widget.onChange!();
|
|
return total;
|
|
}
|
|
|
|
const scale = Number(process.argv[2] ?? "1");
|
|
const categories: Category[] = [];
|
|
for (let i = 0; i < 32; i++) categories.push(new Category(`category-${i}`));
|
|
|
|
let trees = 0;
|
|
for (let round = 0; round < 1500 * scale; round++) trees = (trees + treeWeight(buildTree(5, undefined, round))) % 1000003;
|
|
|
|
let rings = 0;
|
|
for (let round = 0; round < 4000 * scale; round++) rings += buildRing(categories, 40, round).next!.rank;
|
|
|
|
let widgets = 0;
|
|
for (let round = 0; round < 600 * scale; round++) widgets += buildWidgets(100);
|
|
|
|
let members = 0;
|
|
for (const category of categories) members += category.members;
|
|
console.log(`trees ${trees}`);
|
|
console.log(`rings ${rings}`);
|
|
console.log(`widgets ${widgets}`);
|
|
console.log(`members ${members}`);
|