-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcrack-length.js
85 lines (68 loc) · 2.32 KB
/
crack-length.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
const { makeRequest } = require("./lib/request");
const { midsummary } = require("./lib/estimator");
// Guess keys of length b/w 1 and N
const MAX_KEY_LEN = 32;
// How many last observations to use per round
const N_OBSERVATIONS_PER_ROUND = 20;
// How many observation to run before reporting.
// Multiply by some small positive integer (1 < n < 10)
// to make sure we "warm up" before doing actual measurements.
// Probably not necessary, but also useful to fully refresh
// the list of measurements b/w rounds.
const REPORT_EVERY_N_OBSERVATIONS = 2 * N_OBSERVATIONS_PER_ROUND * MAX_KEY_LEN;
/**
* Experiment data, a map from key length to round trip times (RTT)
* @type {{
* [key: number]: BigInt[]
* }}
*/
const experiments = {};
/**
* Total number of performed observations.
* @type {number}
*/
let totalObservations = 0;
/**
* Counting how many times each key length came out on top,
* i.e., #1 in the list of longest observations (aggregated via some function)
* @type {{
* [key: number]: number
* }}
*/
const topPlaces = {};
/**
* @param len {number}
* @param timeDiff {BigInt}
*/
function updateObservations(len, timeDiff) {
/** @type BigInt[] */
const observations = experiments[len] ?? [];
experiments[len] = [timeDiff, ...observations].slice(0, N_OBSERVATIONS_PER_ROUND);
totalObservations += 1;
}
function report() {
const ranking = Object.keys(experiments)
.map(len => [len, midsummary(experiments[len])])
.sort((a, b) => b[1] - a[1]);
const [slowestLen] = ranking[0];
topPlaces[slowestLen] = (topPlaces[slowestLen] ?? 0) + 1;
const report = Object.keys(topPlaces)
.map(l => [l, topPlaces[l]])
.sort((a, b) => b[1] - a[1]) // Descending by total number of top places
.slice(0, 5) // report only top 5
.map(row => `${row[0].padStart(2, ' ')} was the slowest ${row[1]} time(s)`);
console.log("\n" + report.join("\n"));
}
async function guessLength() {
const randomLen = Math.floor(Math.random() * MAX_KEY_LEN) + 1;
const dummyKey = '0'.repeat(randomLen);
const [, timeDiff] = await makeRequest(dummyKey);
updateObservations(randomLen, timeDiff);
if (totalObservations % REPORT_EVERY_N_OBSERVATIONS === 0) {
report();
}
// loop with a chance to terminate
setTimeout(() => guessLength(), 0);
}
// start the infinity loop, finish by pressing Ctrl-C
guessLength();