-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathindex.js
More file actions
166 lines (142 loc) · 5.01 KB
/
index.js
File metadata and controls
166 lines (142 loc) · 5.01 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
import { mkdir, opendir, readFile, writeFile } from 'node:fs/promises'
import { compress, decompress } from 'lzma-native'
import {
merge_nonoverlap,
process_raw_results,
score_run,
focus_areas_map,
get_focus_areas
} from './process-wpt-results.js'
async function read_json_file (path) {
const contents = await readFile(path, {
encoding: 'utf8'
})
return JSON.parse(contents)
}
async function write_json_file (path, json) {
const contents = JSON.stringify(json)
return writeFile(path, contents)
}
async function write_compressed (path, json) {
const string = JSON.stringify(json)
const data = await compress(string, 9)
return writeFile(path, data)
}
async function read_compressed (path) {
const data = await readFile(path)
const string = await decompress(data)
return JSON.parse(string)
}
async function all_runs_sorted (runs_dir) {
const dir = await opendir(`./${runs_dir}`)
const runs = []
for await (const run of dir) {
if (run.name === '.DS_Store') continue
runs.push(run.name)
}
runs.sort()
return runs
}
async function process_chunks (path) {
const dir = await opendir(path)
let result = {}
for await (const chunk of dir) {
if (chunk.name === '.DS_Store') continue
console.log(`Processing chunk ${chunk.name}`)
const chunk_run = await read_json_file(`${path}/${chunk.name}`)
const scored_chunk = process_raw_results(chunk_run)
if (!result.run_info) {
const raw_run_info = scored_chunk.run_info
const matches = raw_run_info
.browser_version
.match(/^Version: Servo ([0-9.]+-[a-f0-9]+)?(-dirty)?$/)
const browser_version = matches && matches.length === 3 ? matches[1] : 'Unknown'
result.run_info = Object.assign(raw_run_info, { browser_version })
}
delete scored_chunk.run_info
result = merge_nonoverlap(result, scored_chunk)
}
sort_test_results(result)
return result
}
// Sorts the keys of the test_scores object alphabetically
function sort_test_results (result) {
console.log('Sorting results')
result.test_scores = into_sorted_map(result.test_scores)
}
// Convert an object into a sorted Map
//
// JS Maps serialize keys in insertion order, so to control the order of JSON serialized output
// we can:
//
// - Convert the object into an array
// - Sort the array by test object key
// - Reinsert the results into a new Map in order
//
// Storing the result in a Map rather a regular object allows us to have full control over the order
function into_sorted_map (obj) {
const arr = Object.entries(obj).map(([key, value]) => ({ key, value }))
arr.sort((a, b) => {
if (a.key < b.key) return -1
if (a.key > b.key) return 1
return 0
})
const map = new Map()
for (const entry of arr) {
map[entry.key] = entry.value
}
return map
}
async function add_run (runs_dir, chunks_dir, date) {
const new_run = await process_chunks(chunks_dir)
await write_compressed(`./${runs_dir}/${date}.xz`, new_run)
}
async function recalc_scores (runs_dir) {
console.log(`Calculating scores for ${runs_dir} directory...`)
const run_results = []
console.log('Enumerating runs')
const all_runs = await all_runs_sorted(runs_dir)
const run_count = all_runs.length
console.log('Reading latest run')
const new_run = await read_compressed(`./${runs_dir}/${all_runs[all_runs.length - 1]}`)
console.log('Building focus area map')
const test_to_areas = focus_areas_map(new_run)
for (const [i, r] of all_runs.entries()) {
const [date] = r.split('.')
console.log(`Reading run ${runs_dir}/${r} (${i}/${run_count})`)
const run = await read_compressed(`./${runs_dir}/${r}`)
console.log(`Calculating score for run ${runs_dir}/${r} (${i}/${run_count})`)
const score = score_run(run, new_run, test_to_areas)
const row = {
date,
wpt_revision: run.run_info.revision.substring(0, 9),
product_revision: run.run_info.browser_version,
scores: score
}
run_results.push(row)
}
return run_results
}
async function main () {
const mode = process.argv[2]
if (!['--add', '--recalc'].includes(mode)) {
throw new Error(`invalid mode specified: ${mode}`)
}
if (mode === '--add') {
const chunks = process.argv[3]
const date = process.argv[4]
await add_run('runs-2020', chunks, date)
}
const run_results = await recalc_scores('runs-2020')
const last_run = run_results[run_results.length - 1]
const focus_areas = get_focus_areas()
console.log('Writing site/scores.json')
await mkdir('./site', { recursive: true })
write_json_file(
'./site/scores.json', { focus_areas, runs: run_results })
console.log('Writing site/scores-last-run.json')
write_json_file(
'./site/scores-last-run.json', { focus_areas, last_run })
console.log('Done')
}
main()