-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcomparison.js
More file actions
209 lines (193 loc) · 6.87 KB
/
Copy pathcomparison.js
File metadata and controls
209 lines (193 loc) · 6.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Shared source for the zig-js / JavaScriptCore comparison benchmark.
//
// Keep this file host-API-free: both runners evaluate these exact bytes. Each
// workload returns a deterministic, exactly representable integer checksum.
// The `jobs` argument is the unit reported by the benchmark driver; parallel
// rows run `jobs` independently in every lane.
function benchmarkArithmetic(jobs, lane) {
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var value = lane + job + 1;
for (var i = 0; i < 100000; i = i + 1)
value = (value + i + lane) % 1000003;
total = total + value;
}
return total;
}
function benchmarkProperties(jobs, lane) {
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var object = { a: lane + job, b: 1, c: 2, d: 3 };
for (var i = 0; i < 25000; i = i + 1) {
object.a = (object.a + i) % 1000003;
object.b = object.b + 1;
object.c = object.a + object.b;
object.d = object.c - object.b;
}
total = total + object.a + object.b + object.c + object.d;
}
return total;
}
function benchmarkPolymorphicProperties(jobs, lane) {
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var base = lane + job + 1;
// Keep `value` at four different slots. The hot access below therefore
// crosses four live receiver shapes instead of one monomorphic object.
var objects = [
{ value: base, a: 1 },
{ b: 2, value: base + 1 },
{ c: 3, d: 4, value: base + 2 },
{ e: 5, f: 6, g: 7, value: base + 3 }
];
var checksum = 0;
for (var i = 0; i < 10000; i = i + 1) {
var object = objects[i & 3];
var next = (object.value + i + lane) % 1000003;
object.value = next;
checksum = checksum + (next & 1023);
}
total = total + checksum + objects[0].value + objects[1].value +
objects[2].value + objects[3].value;
}
return total;
}
function benchmarkObjectChurn(jobs, lane) {
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
// Keep a fixed live ring. Each replacement makes the displaced object
// unreachable, so the timed loop sustains allocation/reclamation pressure
// without retaining an ever-growing graph.
var ring = [];
for (var slot = 0; slot < 256; slot = slot + 1) {
ring.push({
value: lane + job + slot + 1,
stamp: slot & 7,
previous: 0
});
}
for (var i = 0; i < 20000; i = i + 1) {
var index = i & 255;
var displaced = ring[index];
var value = (displaced.value + i + lane) % 1000003;
var fresh = {
value: value,
stamp: i & 7,
previous: displaced.value
};
ring[index] = fresh;
total = total + ((fresh.value + fresh.stamp + fresh.previous) & 1023);
}
for (var tail = 0; tail < ring.length; tail = tail + 1)
total = total + (ring[tail].value & 1023);
}
return total;
}
function benchmarkArrays(jobs, lane) {
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var values = [];
for (var i = 0; i < 10000; i = i + 1)
values.push((i + job + lane) & 65535);
for (var j = 0; j < values.length; j = j + 1)
total = total + values[j];
}
return total;
}
function benchmarkDirectCallStep(value, delta) {
return (value + delta) % 1000003;
}
function benchmarkDirectCalls(jobs, lane) {
// Copy the callee once per lane so shared-realm rows measure ordinary call
// throughput rather than contending on the benchmark's own global binding.
var step = benchmarkDirectCallStep;
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var value = lane + job + 1;
for (var i = 0; i < 10000; i = i + 1)
value = step(value, i);
total = total + value;
}
return total;
}
function benchmarkMethodStep(value, delta) {
return (this.bias + value + delta) % 1000003;
}
function benchmarkMethodCalls(jobs, lane) {
// Each lane owns its receiver. The method reads `this.bias`, so this remains
// a real property lookup and receiver-binding call rather than a direct call
// with decorative object syntax.
var receiver = { bias: lane + 1, step: benchmarkMethodStep };
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var value = job + 1;
for (var i = 0; i < 10000; i = i + 1)
value = receiver.step(value, i);
total = total + value;
}
return total;
}
function benchmarkClosureCalls(jobs, lane) {
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var seed = lane + job + 1;
for (var i = 0; i < 10000; i = i + 1) {
// Fresh identity and a live by-reference capture on every iteration.
// Calling immediately keeps the kernel focused without retaining an
// unbounded closure graph after the job completes.
var closure = function (delta) {
return (seed + delta) % 1000003;
};
seed = closure(i);
}
total = total + seed;
}
return total;
}
function benchmarkArgumentsStep(value, delta) {
// Read through the real per-call arguments object rather than the named
// parameters. This exercises arguments materialization and indexed access.
return (arguments[0] + arguments[1]) % 1000003;
}
function benchmarkArgumentsCalls(jobs, lane) {
var step = benchmarkArgumentsStep;
var total = 0;
for (var job = 0; job < jobs; job = job + 1) {
var value = lane + job + 1;
for (var i = 0; i < 10000; i = i + 1)
value = step(value, i);
total = total + value;
}
return total;
}
var benchmarkFibValue = function benchmarkFibValue(n, state) {
// Keep each call observable so this row continues measuring recursive call
// throughput even when an engine can recognize and memoize the pure
// recurrence. The state is invocation-local, so shared-realm lanes never
// race one counter or produce schedule-dependent checksums.
state.calls = state.calls + 1;
return n < 2 ? n : benchmarkFibValue(n - 1, state) + benchmarkFibValue(n - 2, state);
};
function benchmarkFibonacci(jobs, lane) {
var total = lane;
var state = { calls: 0 };
for (var job = 0; job < jobs; job = job + 1)
total = total + benchmarkFibValue(24, state);
return total + state.calls;
}
function benchmarkFunction(name) {
if (name === "arithmetic") return benchmarkArithmetic;
if (name === "properties") return benchmarkProperties;
if (name === "polymorphic_properties") return benchmarkPolymorphicProperties;
if (name === "object_churn") return benchmarkObjectChurn;
if (name === "arrays") return benchmarkArrays;
if (name === "direct_calls") return benchmarkDirectCalls;
if (name === "method_calls") return benchmarkMethodCalls;
if (name === "closure_calls") return benchmarkClosureCalls;
if (name === "arguments_calls") return benchmarkArgumentsCalls;
if (name === "fibonacci") return benchmarkFibonacci;
throw new Error("unknown benchmark workload: " + name);
}
function runBenchmark(name, jobs, lane) {
return benchmarkFunction(name)(jobs, lane);
}