2
2
3
3
extern crate swc_malloc;
4
4
5
- use std:: fs:: read_to_string;
5
+ use std:: {
6
+ fs:: read_to_string,
7
+ path:: { Path , PathBuf } ,
8
+ process:: Command ,
9
+ } ;
6
10
7
11
use codspeed_criterion_compat:: { black_box, criterion_group, criterion_main, Criterion } ;
8
- use swc_common:: { errors:: HANDLER , sync:: Lrc , FileName , Mark , SourceMap } ;
9
- use swc_ecma_ast:: Program ;
12
+ use swc_common:: { sync:: Lrc , FileName , Mark , SourceMap , GLOBALS } ;
10
13
use swc_ecma_codegen:: text_writer:: JsWriter ;
11
14
use swc_ecma_minifier:: {
12
15
optimize,
13
16
option:: { ExtraOptions , MangleOptions , MinifyOptions } ,
14
17
} ;
15
- use swc_ecma_parser:: parse_file_as_module ;
18
+ use swc_ecma_parser:: parse_file_as_program ;
16
19
use swc_ecma_transforms_base:: { fixer:: fixer, resolver} ;
20
+ use swc_ecma_utils:: parallel:: { Parallel , ParallelExt } ;
21
+ use testing:: CARGO_TARGET_DIR ;
22
+ use walkdir:: WalkDir ;
17
23
18
- pub fn bench_files ( c : & mut Criterion ) {
24
+ fn bench_libs ( c : & mut Criterion ) {
19
25
let mut group = c. benchmark_group ( "es/minifier/libs" ) ;
20
26
group. sample_size ( 10 ) ;
21
27
@@ -45,65 +51,151 @@ pub fn bench_files(c: &mut Criterion) {
45
51
bench_file ( "vue" ) ;
46
52
}
47
53
48
- criterion_group ! ( files , bench_files ) ;
49
- criterion_main ! ( files ) ;
54
+ fn bench_real ( c : & mut Criterion ) {
55
+ let input_dir = CARGO_TARGET_DIR . join ( "swc-minifier-inputs" ) ;
50
56
51
- fn run ( src : & str ) {
52
- testing:: run_test2 ( false , |cm, handler| {
53
- HANDLER . set ( & handler, || {
54
- let fm = cm. new_source_file ( FileName :: Anon . into ( ) , src. into ( ) ) ;
55
-
56
- let unresolved_mark = Mark :: new ( ) ;
57
- let top_level_mark = Mark :: new ( ) ;
58
-
59
- let program = parse_file_as_module (
60
- & fm,
61
- Default :: default ( ) ,
62
- Default :: default ( ) ,
63
- None ,
64
- & mut Vec :: new ( ) ,
65
- )
66
- . map_err ( |err| {
67
- err. into_diagnostic ( & handler) . emit ( ) ;
68
- } )
69
- . map ( Program :: Module )
70
- . map ( |module| module. apply ( resolver ( unresolved_mark, top_level_mark, false ) ) )
57
+ git_clone (
58
+ "https://github.com/kdy1/swc-minifier-inputs.git" ,
59
+ "a967ebba1668d1f78e1b5077bdbdce6ad0bfcaee" ,
60
+ & input_dir,
61
+ ) ;
62
+
63
+ let mut group = c. benchmark_group ( "es/minifier/real" ) ;
64
+ group. sample_size ( 10 ) ;
65
+
66
+ let files = expand_dirs ( & input_dir) ;
67
+ let sources = files
68
+ . iter ( )
69
+ . map ( |path| read_to_string ( path) . unwrap ( ) )
70
+ . collect :: < Vec < _ > > ( ) ;
71
+
72
+ group. bench_function ( "es/minifier/real/sequential" , |b| {
73
+ b. iter ( || {
74
+ // We benchmark full time, including time for creating cm, handler
75
+
76
+ for src in & sources {
77
+ run ( src) ;
78
+ }
79
+ } )
80
+ } ) ;
81
+
82
+ group. bench_function ( "es/minifier/real/parallel" , |b| {
83
+ b. iter ( || {
84
+ // We benchmark full time, including time for creating cm, handler
85
+
86
+ GLOBALS . set ( & Default :: default ( ) , || {
87
+ Worker :: default ( ) . maybe_par ( 0 , & * sources, |_, src| run ( src) ) ;
88
+ } ) ;
89
+ } )
90
+ } ) ;
91
+ }
92
+
93
+ #[ derive( Default , Clone , Copy ) ]
94
+ struct Worker { }
95
+
96
+ impl Parallel for Worker {
97
+ fn create ( & self ) -> Self {
98
+ * self
99
+ }
100
+
101
+ fn merge ( & mut self , _other : Self ) { }
102
+ }
103
+
104
+ fn git_clone ( url : & str , commit : & str , path : & Path ) {
105
+ if !path. join ( ".git" ) . exists ( ) {
106
+ let status = Command :: new ( "git" )
107
+ . arg ( "clone" )
108
+ . arg ( url)
109
+ . arg ( path)
110
+ . status ( )
71
111
. unwrap ( ) ;
72
112
73
- let output = optimize (
74
- program,
75
- cm. clone ( ) ,
76
- None ,
77
- None ,
78
- & MinifyOptions {
79
- rename : false ,
80
- compress : Some ( Default :: default ( ) ) ,
81
- mangle : Some ( MangleOptions {
82
- props : None ,
83
- top_level : Some ( true ) ,
84
- keep_class_names : false ,
85
- keep_fn_names : false ,
86
- keep_private_props : false ,
87
- ie8 : false ,
88
- ..Default :: default ( )
89
- } ) ,
90
- wrap : false ,
91
- enclose : false ,
92
- } ,
93
- & ExtraOptions {
94
- unresolved_mark,
95
- top_level_mark,
96
- mangle_name_cache : None ,
97
- } ,
98
- ) ;
99
-
100
- let output = output. apply ( fixer ( None ) ) ;
101
-
102
- let code = print ( cm, & [ output] , true ) ;
103
-
104
- black_box ( code) ;
105
- Ok ( ( ) )
113
+ if !status. success ( ) {
114
+ panic ! ( "failed to clone `{}` to `{}`" , url, path. display( ) ) ;
115
+ }
116
+ }
117
+
118
+ let status = Command :: new ( "git" )
119
+ . current_dir ( path)
120
+ . args ( [ "checkout" , commit] )
121
+ . status ( )
122
+ . unwrap ( ) ;
123
+
124
+ if !status. success ( ) {
125
+ panic ! ( "failed to checkout `{}` in `{}`" , commit, path. display( ) ) ;
126
+ }
127
+ }
128
+
129
+ /// Return the whole input files as abolute path.
130
+ fn expand_dirs ( dir : & Path ) -> Vec < PathBuf > {
131
+ WalkDir :: new ( dir)
132
+ . into_iter ( )
133
+ . filter_map ( Result :: ok)
134
+ . filter_map ( |entry| {
135
+ if entry. metadata ( ) . map ( |v| v. is_file ( ) ) . unwrap_or ( false ) {
136
+ Some ( entry. into_path ( ) )
137
+ } else {
138
+ None
139
+ }
106
140
} )
141
+ . filter ( |path| path. extension ( ) . map ( |ext| ext == "js" ) . unwrap_or ( false ) )
142
+ . collect :: < Vec < _ > > ( )
143
+ }
144
+
145
+ fn run ( src : & str ) {
146
+ testing:: run_test2 ( false , |cm, handler| {
147
+ let fm = cm. new_source_file ( FileName :: Anon . into ( ) , src. into ( ) ) ;
148
+
149
+ let unresolved_mark = Mark :: new ( ) ;
150
+ let top_level_mark = Mark :: new ( ) ;
151
+
152
+ let Ok ( program) = parse_file_as_program (
153
+ & fm,
154
+ Default :: default ( ) ,
155
+ Default :: default ( ) ,
156
+ None ,
157
+ & mut Vec :: new ( ) ,
158
+ )
159
+ . map_err ( |err| {
160
+ err. into_diagnostic ( & handler) . emit ( ) ;
161
+ } )
162
+ . map ( |program| program. apply ( resolver ( unresolved_mark, top_level_mark, false ) ) ) else {
163
+ return Ok ( ( ) ) ;
164
+ } ;
165
+
166
+ let output = optimize (
167
+ program,
168
+ cm. clone ( ) ,
169
+ None ,
170
+ None ,
171
+ & MinifyOptions {
172
+ rename : false ,
173
+ compress : Some ( Default :: default ( ) ) ,
174
+ mangle : Some ( MangleOptions {
175
+ props : None ,
176
+ top_level : Some ( true ) ,
177
+ keep_class_names : false ,
178
+ keep_fn_names : false ,
179
+ keep_private_props : false ,
180
+ ie8 : false ,
181
+ ..Default :: default ( )
182
+ } ) ,
183
+ wrap : false ,
184
+ enclose : false ,
185
+ } ,
186
+ & ExtraOptions {
187
+ unresolved_mark,
188
+ top_level_mark,
189
+ mangle_name_cache : None ,
190
+ } ,
191
+ ) ;
192
+
193
+ let output = output. apply ( fixer ( None ) ) ;
194
+
195
+ let code = print ( cm, & [ output] , true ) ;
196
+
197
+ black_box ( code) ;
198
+ Ok ( ( ) )
107
199
} )
108
200
. unwrap ( ) ;
109
201
}
@@ -126,3 +218,6 @@ fn print<N: swc_ecma_codegen::Node>(cm: Lrc<SourceMap>, nodes: &[N], minify: boo
126
218
127
219
String :: from_utf8 ( buf) . unwrap ( )
128
220
}
221
+
222
+ criterion_group ! ( bench_all, bench_libs, bench_real) ;
223
+ criterion_main ! ( bench_all) ;
0 commit comments