forked from rocicorp/replicache
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathperf.js
More file actions
129 lines (112 loc) · 2.81 KB
/
Copy pathperf.js
File metadata and controls
129 lines (112 loc) · 2.81 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
/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-check
/* eslint-env browser, es2020 */
import Replicache from '../out/mod.js';
const valSize = 1024;
function randomString(len) {
var arr = new Uint8Array(len);
crypto.getRandomValues(arr);
return new TextDecoder('ascii').decode(arr);
}
/**
* @param {string} name
*/
function deleteDatabase(name) {
return new Promise((resolve, reject) => {
const req = indexedDB.deleteDatabase(name);
req.onsuccess = resolve;
req.onerror = reject;
});
}
let counter = 0;
async function makeRep() {
const name = `bench${counter++}`;
await deleteDatabase(name);
return new Replicache({
diffServerURL: '',
name,
syncInterval: null,
});
}
/**
* @param {Replicache} rep
*/
async function populate(rep, {numKeys}) {
const set = rep.register('populate', async tx => {
for (let i = 0; i < numKeys; i++) {
await tx.put(`key${i}`, randomString(valSize));
}
});
await set({});
}
async function benchmarkPopulate(bench, opts) {
const rep = await makeRep();
if (!opts.clean) {
await populate(rep, opts);
}
bench.reset();
bench.setName(
`populate ${valSize}x${opts.numKeys} (${opts.clean ? 'clean' : 'dirty'})`,
);
bench.setSize(opts.numKeys * valSize);
await populate(rep, opts);
}
async function benchmarkScan(bench, opts) {
const rep = await makeRep();
bench.setName(`scan ${valSize}x${opts.numKeys}`);
bench.setSize(opts.numKeys * valSize);
await populate(rep, opts);
bench.reset();
await rep.query(async tx => {
let count = 0;
for await (const value of tx.scan()) {
// use the value to be confident we're not optimizing away.
// @ts-ignore
count += value.length;
}
console.log(count);
});
}
async function benchmark(fn) {
const runs = 5;
const times = [];
let sum = 0;
let name = String(fn);
let size = 0;
for (let i = 0; i < runs; i++) {
let t0 = Date.now();
await fn({
reset: () => {
t0 = Date.now();
},
setName: n => (name = n),
setSize: s => (size = s),
});
const dur = Date.now() - t0;
times.push(dur);
sum += dur;
}
console.log(sum);
times.sort();
const median = times[Math.floor(runs / 2)];
const value = toMB((size / median) * 1000) + '/s';
return {name, value, median};
}
const benchmarks = [
bench => benchmarkPopulate(bench, {numKeys: 1000, clean: true}),
bench => benchmarkPopulate(bench, {numKeys: 1000, clean: false}),
bench => benchmarkScan(bench, {numKeys: 1000}),
bench => benchmarkScan(bench, {numKeys: 5000}),
];
function toMB(bytes) {
return (bytes / 2 ** 20).toFixed(2) + ' MB';
}
let current = 0;
async function nextTest() {
if (current < benchmarks.length) {
return await benchmark(benchmarks[current++]);
}
return null;
}
// @ts-ignore
window.nextTest = nextTest;