1
+ /**
2
+ * @file table.mjs
3
+ * @description Generate a table from criterion output.
4
+ *
5
+ * Usage:
6
+ * pnpm table [options]
7
+ *
8
+ * # Options
9
+ * -f,--format <format> Output format. 'md' or 'csv'. Default: 'md'
10
+ * -o,--output <path> Output file path. Prints to stdout if not set.
11
+ */
1
12
import fs from 'node:fs'
2
13
import { markdownTable } from 'markdown-table'
3
14
@@ -24,29 +35,113 @@ async function readData() {
24
35
25
36
return data
26
37
}
38
+ /**
39
+ * @param {string[] } argv
40
+ */
41
+ function parseArgs ( argv ) {
42
+ const opts = {
43
+ /**
44
+ * output format. Markdown or CSV.
45
+ * @type {'markdown' | 'csv' }
46
+ */
47
+ format : 'markdown' ,
48
+ /**
49
+ * Path to output file. `null` prints to stdout.
50
+ * @type {string | null }
51
+ */
52
+ output : null ,
53
+ } ;
27
54
28
- async function main ( ) {
55
+ for ( let arg = argv . shift ( ) ; arg ; arg = argv . shift ( ) ) {
56
+ switch ( arg ) {
57
+ case '-f' :
58
+ case '--format' : {
59
+
60
+ const format = argv . shift ( ) ?. trim ( ) ?. toLowerCase ( ) ;
61
+ if ( ! format ) throw new TypeError ( '--format flag requires an argument' ) ;
62
+ switch ( format ) {
63
+ case 'md' :
64
+ case 'markdown' :
65
+ opts . format = 'markdown' ;
66
+ break ;
67
+ case 'csv' :
68
+ opts . format = 'csv' ;
69
+ break ;
70
+ default :
71
+ throw new TypeError ( `Invalid format '${ format } ', expected 'md' or 'csv'` ) ;
72
+ }
73
+ break ;
74
+ }
75
+
76
+ case '-o' :
77
+ case '--output' : {
78
+ opts . output = argv . shift ( ) ;
79
+ break ;
80
+ }
81
+
82
+ // in case someone runs `pnpm table -- --format csv`
83
+ case '--' :
84
+ continue
85
+ }
86
+ }
87
+
88
+ return opts ;
89
+ }
90
+
91
+ async function main ( argv ) {
29
92
const data = await readData ( ) ;
30
93
const groups = Object . keys ( data ) ;
31
94
const columns = Object . keys ( data [ groups [ 0 ] ] ) ;
32
95
const rows = Object . keys ( data [ groups [ 0 ] ] [ columns [ 0 ] ] ) ;
96
+ const options = parseArgs ( argv ) ;
33
97
98
+ let out = '' ;
34
99
35
- for ( const group of groups ) {
36
- console . log ( `### ${ group } ` ) ;
37
- console . log ( )
38
- const table = [ [ "" , ...columns ] ] ;
39
- for ( const row of rows ) {
40
- const column_numbers = columns . map ( ( column ) => data [ group ] [ column ] [ row ] . duration_ms ) ;
41
- const minimum = Math . min ( ...column_numbers ) ;
42
- const column_values = column_numbers . map ( ( number ) => {
43
- return `\`${ number . toFixed ( 1 ) } ms\` (${ ( number / minimum ) . toFixed ( 2 ) } x)`
44
- } ) ;
45
- table . push ( [ row , ...column_values ] ) ;
100
+ switch ( options . format ) {
101
+ case 'markdown' : {
102
+ for ( const group of groups ) {
103
+ out += `### ${ group } \n` ;
104
+ const table = [ [ "" , ...columns ] ] ;
105
+ for ( const row of rows ) {
106
+ const column_numbers = columns . map ( ( column ) => data [ group ] [ column ] [ row ] . duration_ms ) ;
107
+ const minimum = Math . min ( ...column_numbers ) ;
108
+ const column_values = column_numbers . map ( ( number ) => {
109
+ return `\`${ number . toFixed ( 1 ) } ms\` (${ ( number / minimum ) . toFixed ( 2 ) } x)`
110
+ } ) ;
111
+ table . push ( [ row , ...column_values ] ) ;
112
+ }
113
+ out += markdownTable ( table ) + '\n' ;
114
+ }
115
+ break
46
116
}
47
- console . log ( markdownTable ( table ) ) ;
48
- console . log ( )
117
+
118
+ case 'csv' : {
119
+ const header = [ 'group' , 'bench_name' , 'tool' , 'measurement' , 'duration_ms' ] ;
120
+ out += header . join ( ',' ) + '\n' ;
121
+
122
+ for ( const group of groups ) {
123
+ // swc, oxc
124
+ for ( const column of columns ) {
125
+ const benches = data [ group ] [ column ]
126
+ for ( const bench in benches ) {
127
+ const { duration_ms } = benches [ bench ] ;
128
+ out += `${ group } ,${ bench } ,${ column } ,duration,${ duration_ms } \n` ;
129
+ }
130
+ }
131
+ }
132
+ }
133
+ break ;
134
+
135
+ default :
136
+ throw new TypeError ( `Unexpected output format '${ options . format } '` ) ;
137
+ }
138
+
139
+ if ( ! options . output ) {
140
+ console . log ( out ) ;
141
+ } else {
142
+ await fs . promises . writeFile ( options . output , out , 'utf8' ) ;
143
+ console . log ( `Saved table to ${ options . output } ` ) ;
49
144
}
50
145
}
51
146
52
- main ( )
147
+ main ( process . argv . slice ( 2 ) ) . catch ( console . error ) ;
0 commit comments