-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.js
129 lines (106 loc) · 3.39 KB
/
script.js
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
/**
* Util for loading web assembly.
*/
const loadWebAssembly = fileName => (
fetch(fileName)
.then(response => response.arrayBuffer() )
.then(bytes => WebAssembly.instantiate(bytes, {}) )
.then(result => result.instance.exports)
);
/**
* Util for loading and printing load time of web assembly.
*/
const loadTimeLogs = [];
const loadAndLogWASM = fileName => {
const startTime = performance.now();
const loader = loadWebAssembly(fileName);
loader.then(_ => {
const log = [`Loaded -> ${fileName} in`, +(performance.now() - startTime).toFixed(), 'ms'];
loadTimeLogs.push(log);
console.log(...log);
});
return loader;
}
/**
* Simple benchmark runner.
*/
const runBenchmark = (rangeMax, iteration, funcs) => {
console.log(`Summing squares of range from 1 to ${rangeMax} for ${iteration} times.`);
const funcCount = funcs.length;
const iterate = [...Array(iteration).keys()];
let results = Array(funcCount).fill(null).map(() => []);
iterate.forEach(iterNo => {
console.log(`> Running iteration number (${iterNo+1}/${iteration})...`);
funcs.forEach(([name, func], index) => {
console.log(`--> Calculating benchmark for ${name} (${index+1}/${funcCount})...`);
const startTime = performance.now();
const result = func(rangeMax);
const execTime = performance.now() - startTime;
results[index].push({
lang: name,
time: +execTime.toFixed(0),
value: result
});
});
});
results = results.map((result, index) => {
const { lang, value } = result[0];
const averageTime = result.reduce((acc, {time}) => acc + time, 0) / iteration;
// Being sure about things.
const allSameValues = result.every(item => item.value === value);
const allSameLangs = result.every(item => item.lang === lang);
if (!allSameValues || !allSameLangs) {
throw new Error(`Something wrong! Values/Langs are not same somewhere...`);
}
return {
'Language': lang,
'Average Time (ms)': +averageTime.toFixed(0),
'Result': value
};
});
const allSameResults = results.every(item => item.Result === results[0].Result);
console.clear();
console.log('Benchmark completed.')
console.log('');
console.log('Load times:');
loadTimeLogs.forEach(log => console.log(...log));
console.log('');
console.log('Benchmark results:');
console.table(results);
console.log(allSameResults ? 'All results are equal ✅' : 'All results are not equal ❌');
};
/**
* Imparative JavaScript squarer func.
*/
const JSSquarer = n => {
var total = 0;
for (var i = 0; i <= n; i++) {
total += i * i
}
return total;
};
/**
* Our main test function.
*/
async function runBenchmarks() {
// Load wasms.
console.log('');
console.log('Loading Wasm modules...');
const [ ByHand, CPP, Rust ] = await Promise.all([
loadAndLogWASM('by-hand/squarer.wasm'),
loadAndLogWASM('c++/squarer.wasm'),
loadAndLogWASM('rust/squarer.wasm'),
]);
console.log('');
// Run benchmarks.
runBenchmark(1000000000, 10, [
['Native JavaScript', JSSquarer],
['Wasm Written By Hand', ByHand.sumSquares],
['C++ Compiled to Wasm', CPP._Z10sumSquaresi],
['Rust Compiled to Wasm', n => Rust.SumSquares(n+1)], // Rust ranges doesnt count last item so we have this fix for now..
]);
}
/**
* Run main at the beginning.
*/
console.log('Call runBenchmarks() function to run benchmarks...');