Skip to content

Commit 2535931

Browse files
committed
a few version for comparison
1 parent e7b5b8c commit 2535931

File tree

3 files changed

+121
-36
lines changed

3 files changed

+121
-36
lines changed

Runtime/bench/_version2.ts

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,74 @@ import { globalVariable } from "../src/find-global.js";
22
import { ref } from "../src/types.js";
33

44
export class JSObjectSpace_v2 {
5-
private _entryByValue: Map<any, { id: number; rc: number }>;
6-
private _values: (any | undefined)[];
7-
private _refCounts: number[];
5+
private _idByValue: Map<any, number>;
6+
private _valueById: Record<number, any>;
7+
private _refCountById: Record<number, number | undefined>;
88
private _nextRef: number;
99

1010
constructor() {
11-
this._values = [];
12-
this._values[0] = undefined;
13-
this._values[1] = globalVariable;
14-
15-
this._entryByValue = new Map();
16-
this._entryByValue.set(globalVariable, { id: 1, rc: 1 });
17-
18-
this._refCounts = [];
19-
this._refCounts[0] = 0;
20-
this._refCounts[1] = 1;
11+
this._idByValue = new Map();
12+
this._idByValue.set(globalVariable, 1);
13+
this._valueById = Object.create(null);
14+
this._refCountById = Object.create(null);
15+
this._valueById[1] = globalVariable;
16+
this._refCountById[1] = 1;
2117

2218
// 0 is invalid, 1 is globalThis.
2319
this._nextRef = 2;
2420
}
2521

2622
retain(value: any) {
27-
const entry = this._entryByValue.get(value);
28-
if (entry) {
29-
entry.rc++;
30-
this._refCounts[entry.id]++;
31-
return entry.id;
23+
const id = this._idByValue.get(value);
24+
if (id !== undefined) {
25+
this._refCountById[id]!++;
26+
return id;
3227
}
3328

34-
const id = this._nextRef++;
35-
this._values[id] = value;
36-
this._refCounts[id] = 1;
37-
this._entryByValue.set(value, { id, rc: 1 });
38-
return id;
29+
const newId = this._nextRef++;
30+
this._valueById[newId] = value;
31+
this._refCountById[newId] = 1;
32+
this._idByValue.set(value, newId);
33+
return newId;
3934
}
4035

4136
retainByRef(ref: ref) {
42-
return this.retain(this.getObject(ref));
37+
const rc = this._refCountById[ref];
38+
if (rc === undefined) {
39+
throw new ReferenceError(
40+
"Attempted to retain invalid reference " + ref,
41+
);
42+
}
43+
this._refCountById[ref] = rc + 1;
44+
return ref;
4345
}
4446

4547
release(ref: ref) {
46-
const value = this._values[ref];
47-
const entry = this._entryByValue.get(value)!;
48-
entry.rc--;
49-
this._refCounts[ref]--;
50-
if (entry.rc != 0) return;
48+
const rc = this._refCountById[ref];
49+
if (rc === undefined) {
50+
throw new ReferenceError(
51+
"Attempted to release invalid reference " + ref,
52+
);
53+
}
54+
const next = rc - 1;
55+
if (next !== 0) {
56+
this._refCountById[ref] = next;
57+
return;
58+
}
5159

52-
this._entryByValue.delete(value);
53-
// Keep IDs monotonic; clear slot and leave possible holes.
54-
this._values[ref] = undefined;
55-
this._refCounts[ref] = 0;
60+
const value = this._valueById[ref];
61+
this._idByValue.delete(value);
62+
delete this._valueById[ref];
63+
delete this._refCountById[ref];
5664
}
5765

5866
getObject(ref: ref) {
59-
const value = this._values[ref];
60-
if (value === undefined) {
67+
const rc = this._refCountById[ref];
68+
if (rc === undefined) {
6169
throw new ReferenceError(
6270
"Attempted to read invalid reference " + ref,
6371
);
6472
}
65-
return value;
73+
return this._valueById[ref];
6674
}
6775
}

Runtime/bench/_version3.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { globalVariable } from "../src/find-global.js";
2+
import { ref } from "../src/types.js";
3+
4+
export class JSObjectSpace_v3 {
5+
private _idByValue: Map<any, number>;
6+
private _valueById: Map<number, any>;
7+
private _refCountById: Map<number, number>;
8+
private _nextRef: number;
9+
10+
constructor() {
11+
this._idByValue = new Map();
12+
this._idByValue.set(globalVariable, 1);
13+
this._valueById = new Map();
14+
this._refCountById = new Map();
15+
this._valueById.set(1, globalVariable);
16+
this._refCountById.set(1, 1);
17+
18+
// 0 is invalid, 1 is globalThis.
19+
this._nextRef = 2;
20+
}
21+
22+
retain(value: any) {
23+
const id = this._idByValue.get(value);
24+
if (id !== undefined) {
25+
this._refCountById.set(id, this._refCountById.get(id)! + 1);
26+
return id;
27+
}
28+
29+
const newId = this._nextRef++;
30+
this._valueById.set(newId, value);
31+
this._refCountById.set(newId, 1);
32+
this._idByValue.set(value, newId);
33+
return newId;
34+
}
35+
36+
retainByRef(ref: ref) {
37+
const rc = this._refCountById.get(ref);
38+
if (rc === undefined) {
39+
throw new ReferenceError(
40+
"Attempted to retain invalid reference " + ref,
41+
);
42+
}
43+
this._refCountById.set(ref, rc + 1);
44+
return ref;
45+
}
46+
47+
release(ref: ref) {
48+
const rc = this._refCountById.get(ref);
49+
if (rc === undefined) {
50+
throw new ReferenceError(
51+
"Attempted to release invalid reference " + ref,
52+
);
53+
}
54+
const next = rc - 1;
55+
if (next !== 0) {
56+
this._refCountById.set(ref, next);
57+
return;
58+
}
59+
60+
const value = this._valueById.get(ref);
61+
this._idByValue.delete(value);
62+
this._valueById.delete(ref);
63+
this._refCountById.delete(ref);
64+
}
65+
66+
getObject(ref: ref) {
67+
const rc = this._refCountById.get(ref);
68+
if (rc === undefined) {
69+
throw new ReferenceError(
70+
"Attempted to read invalid reference " + ref,
71+
);
72+
}
73+
return this._valueById.get(ref);
74+
}
75+
}

Runtime/bench/bench-runner.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { JSObjectSpace } from "../src/object-heap.js";
77
import { JSObjectSpaceOriginal } from "./_original.js";
88
import { JSObjectSpace_v2 } from "./_version2.js";
9+
import { JSObjectSpace_v3 } from "./_version3.js";
910

1011
export interface HeapLike {
1112
retain(value: unknown): number;
@@ -96,6 +97,7 @@ function main() {
9697
const implementations: Array<{ name: string; Heap: new () => HeapLike }> = [
9798
{ name: "JSObjectSpaceOriginal", Heap: JSObjectSpaceOriginal },
9899
{ name: "JSObjectSpace_v2 (ref++, single map)", Heap: JSObjectSpace_v2 },
100+
{ name: "JSObjectSpace_v3 (ref++, all maps)", Heap: JSObjectSpace_v3 },
99101
{ name: "JSObjectSpace (current)", Heap: JSObjectSpace }
100102
];
101103

0 commit comments

Comments
 (0)