-
-
Notifications
You must be signed in to change notification settings - Fork 152
/
bench.ts
128 lines (116 loc) · 3.38 KB
/
bench.ts
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
import b from 'benny'
import fs from 'fs'
import { ts as sg } from '@ast-grep/napi'
import * as babel from '@babel/core'
import oxc from '@oxidation-compiler/napi'
import * as swc from '@swc/core'
import * as ts from 'typescript'
import Parser from 'tree-sitter'
// because tree-sitter-typescript does not have d.ts
const tresSitterTS = require('tree-sitter-typescript').typescript
const treeSitter = new Parser()
treeSitter.setLanguage(tresSitterTS)
function prepareCases() {
const tsEntry = fs.readFileSync('./fixtures/tsc.ts.fixture', 'utf8')
const vueRef = fs.readFileSync('./fixtures/ref.ts.fixture', 'utf8')
const tsChecker = fs.readFileSync('./fixtures/checker.ts.fixture', 'utf8')
return [
['Parse One Line', 'let a = 123'],
['Parse Small File', tsEntry],
['Parse Medium File', vueRef],
['Parse Huge File', tsChecker],
]
}
const CONCURRENCY = 5
function concurrent(f: () => unknown) {
return () => {
const tasks = Array(CONCURRENCY).fill(undefined).map(() => f())
return Promise.all(tasks)
}
}
export function parseSyncBench(source: string) {
const tasks = {
'ast-grep sync parse': () => {
sg.parse(source)
},
'tree-sitter sync parse': () => {
treeSitter.parse(source)
},
'babel sync parse': () => {
babel.parseSync(source, {
plugins: ['@babel/plugin-syntax-typescript'],
sourceType: 'module',
})
},
'oxc sync parse': () => {
JSON.parse(
oxc.parseSync(source, {
sourceType: 'module',
sourceFilename: 'test.ts',
}).program,
)
},
'swc sync parse': () => {
swc.parseSync(source, {
syntax: 'typescript',
})
},
'TypeScript sync parse': () => {
ts.createSourceFile('benchmark.ts', source, ts.ScriptTarget.Latest)
},
}
const newTasks = Object.entries(tasks).map(([n, f]) => [n, concurrent(f)])
return Object.fromEntries(newTasks)
}
function parseAsyncBench(source: string) {
const tasks = {
'ast-grep async parse': () => sg.parseAsync(source),
'tree-sitter parse(not async)': async () => {
treeSitter.parse(source)
},
'babel async parse': () =>
babel.parseAsync(source, {
plugins: ['@babel/plugin-syntax-typescript'],
sourceType: 'module',
}),
'oxc async parse': async () => {
const src = await oxc.parseAsync(source, {
sourceType: 'module',
sourceFilename: 'test.ts',
})
JSON.parse(src.program)
},
'swc async parse': () =>
swc.parse(source, {
syntax: 'typescript',
}),
'TypeScript parse(not async)': async () => {
ts.createSourceFile('benchmark.ts', source, ts.ScriptTarget.Latest)
},
}
const newTasks = Object.entries(tasks).map(([n, f]) => [n, concurrent(f)])
return Object.fromEntries(newTasks)
}
async function run(benchGenerator: (s: string) => Record<string, () => unknown>) {
const cases = prepareCases()
for (const [title, source] of cases) {
const benches = benchGenerator(source)
await b.suite(
`${benchGenerator.name}: ${title}`,
...Object.entries(benches).map(([runnerName, runner]) =>
b.add(runnerName, runner),
),
b.cycle(),
b.complete(),
)
}
}
async function benchmark() {
await run(parseSyncBench).catch((e) => {
console.error(e)
})
await run(parseAsyncBench).catch((e) => {
console.error(e)
})
}
benchmark()