1
+ use benchsuite:: fixtures;
1
2
use cargo:: core:: compiler:: { CompileKind , RustcTargetData } ;
2
- use cargo:: core:: resolver:: features:: { CliFeatures , FeatureOpts , FeatureResolver , ForceAllTargets } ;
3
- use cargo:: core:: resolver:: { HasDevUnits , ResolveBehavior } ;
3
+ use cargo:: core:: resolver:: features:: { FeatureOpts , FeatureResolver } ;
4
+ use cargo:: core:: resolver:: { CliFeatures , ForceAllTargets , HasDevUnits , ResolveBehavior } ;
4
5
use cargo:: core:: { PackageIdSpec , Workspace } ;
5
6
use cargo:: ops:: WorkspaceResolve ;
6
7
use cargo:: Config ;
7
8
use criterion:: { criterion_group, criterion_main, Criterion } ;
8
- use std:: fs;
9
- use std:: path:: { Path , PathBuf } ;
10
- use std:: process:: Command ;
11
- use url:: Url ;
12
-
13
- // This is an arbitrary commit that existed when I started. This helps
14
- // ensure consistent results. It can be updated if needed, but that can
15
- // make it harder to compare results with older versions of cargo.
16
- const CRATES_IO_COMMIT : & str = "85f7bfd61ea4fee08ec68c468762e886b2aebec6" ;
17
-
18
- fn setup ( ) {
19
- create_home ( ) ;
20
- create_target_dir ( ) ;
21
- clone_index ( ) ;
22
- unpack_workspaces ( ) ;
23
- }
24
-
25
- fn root ( ) -> PathBuf {
26
- let mut p = PathBuf :: from ( env ! ( "CARGO_TARGET_TMPDIR" ) ) ;
27
- p. push ( "bench" ) ;
28
- p
29
- }
30
-
31
- fn target_dir ( ) -> PathBuf {
32
- let mut p = root ( ) ;
33
- p. push ( "target" ) ;
34
- p
35
- }
36
-
37
- fn cargo_home ( ) -> PathBuf {
38
- let mut p = root ( ) ;
39
- p. push ( "chome" ) ;
40
- p
41
- }
42
-
43
- fn index ( ) -> PathBuf {
44
- let mut p = root ( ) ;
45
- p. push ( "index" ) ;
46
- p
47
- }
48
-
49
- fn workspaces_path ( ) -> PathBuf {
50
- let mut p = root ( ) ;
51
- p. push ( "workspaces" ) ;
52
- p
53
- }
54
-
55
- fn registry_url ( ) -> Url {
56
- Url :: from_file_path ( index ( ) ) . unwrap ( )
57
- }
58
-
59
- fn create_home ( ) {
60
- let home = cargo_home ( ) ;
61
- if !home. exists ( ) {
62
- fs:: create_dir_all ( & home) . unwrap ( ) ;
63
- }
64
- fs:: write (
65
- home. join ( "config.toml" ) ,
66
- format ! (
67
- r#"
68
- [source.crates-io]
69
- replace-with = 'local-snapshot'
70
-
71
- [source.local-snapshot]
72
- registry = '{}'
73
- "# ,
74
- registry_url( )
75
- ) ,
76
- )
77
- . unwrap ( ) ;
78
- }
79
-
80
- fn create_target_dir ( ) {
81
- // This is necessary to ensure the .rustc_info.json file is written.
82
- // Otherwise it won't be written, and it is very expensive to create.
83
- if !target_dir ( ) . exists ( ) {
84
- std:: fs:: create_dir_all ( target_dir ( ) ) . unwrap ( ) ;
85
- }
86
- }
87
-
88
- /// This clones crates.io at a specific point in time into tmp/index.
89
- fn clone_index ( ) {
90
- let index = index ( ) ;
91
- let maybe_git = |command : & str | {
92
- let status = Command :: new ( "git" )
93
- . current_dir ( & index)
94
- . args ( command. split_whitespace ( ) . collect :: < Vec < _ > > ( ) )
95
- . status ( )
96
- . expect ( "git should be installed" ) ;
97
- status. success ( )
98
- } ;
99
- let git = |command : & str | {
100
- if !maybe_git ( command) {
101
- panic ! ( "failed to run git command: {}" , command) ;
102
- }
103
- } ;
104
- if index. exists ( ) {
105
- if maybe_git ( & format ! (
106
- "rev-parse -q --verify {}^{{commit}}" ,
107
- CRATES_IO_COMMIT
108
- ) ) {
109
- // Already fetched.
110
- return ;
111
- }
112
- } else {
113
- fs:: create_dir_all ( & index) . unwrap ( ) ;
114
- git ( "init --bare" ) ;
115
- git ( "remote add origin https://github.com/rust-lang/crates.io-index" ) ;
116
- }
117
- git ( & format ! ( "fetch origin {}" , CRATES_IO_COMMIT ) ) ;
118
- git ( "branch -f master FETCH_HEAD" ) ;
119
- }
120
-
121
- /// This unpacks the compressed workspace skeletons into tmp/workspaces.
122
- fn unpack_workspaces ( ) {
123
- let ws_dir = Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) )
124
- . parent ( )
125
- . unwrap ( )
126
- . join ( "workspaces" ) ;
127
- let archives = fs:: read_dir ( ws_dir)
128
- . unwrap ( )
129
- . map ( |e| e. unwrap ( ) . path ( ) )
130
- . filter ( |p| p. extension ( ) == Some ( std:: ffi:: OsStr :: new ( "tgz" ) ) ) ;
131
- for archive in archives {
132
- let name = archive. file_stem ( ) . unwrap ( ) ;
133
- let f = fs:: File :: open ( & archive) . unwrap ( ) ;
134
- let f = flate2:: read:: GzDecoder :: new ( f) ;
135
- let dest = workspaces_path ( ) . join ( & name) ;
136
- if dest. exists ( ) {
137
- fs:: remove_dir_all ( & dest) . unwrap ( ) ;
138
- }
139
- let mut archive = tar:: Archive :: new ( f) ;
140
- archive. unpack ( workspaces_path ( ) ) . unwrap ( ) ;
141
- }
142
- }
9
+ use std:: path:: Path ;
143
10
144
11
struct ResolveInfo < ' cfg > {
145
12
ws : Workspace < ' cfg > ,
@@ -152,36 +19,12 @@ struct ResolveInfo<'cfg> {
152
19
ws_resolve : WorkspaceResolve < ' cfg > ,
153
20
}
154
21
155
- /// Vec of `(ws_name, ws_root)`.
156
- fn workspaces ( ) -> Vec < ( String , PathBuf ) > {
157
- // CARGO_BENCH_WORKSPACES can be used to override, otherwise it just uses
158
- // the workspaces in the workspaces directory.
159
- let mut ps: Vec < _ > = match std:: env:: var_os ( "CARGO_BENCH_WORKSPACES" ) {
160
- Some ( s) => std:: env:: split_paths ( & s) . collect ( ) ,
161
- None => fs:: read_dir ( workspaces_path ( ) )
162
- . unwrap ( )
163
- . map ( |e| e. unwrap ( ) . path ( ) )
164
- // These currently fail in most cases on Windows due to long
165
- // filenames in the git checkouts.
166
- . filter ( |p| {
167
- !( cfg ! ( windows)
168
- && matches ! ( p. file_name( ) . unwrap( ) . to_str( ) . unwrap( ) , "servo" | "tikv" ) )
169
- } )
170
- . collect ( ) ,
171
- } ;
172
- // Sort so it is consistent.
173
- ps. sort ( ) ;
174
- ps. into_iter ( )
175
- . map ( |p| ( p. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_owned ( ) , p) )
176
- . collect ( )
177
- }
178
-
179
22
/// Helper for resolving a workspace. This will run the resolver once to
180
23
/// download everything, and returns all the data structures that are used
181
24
/// during resolution.
182
25
fn do_resolve < ' cfg > ( config : & ' cfg Config , ws_root : & Path ) -> ResolveInfo < ' cfg > {
183
26
let requested_kinds = [ CompileKind :: Host ] ;
184
- let ws = cargo :: core :: Workspace :: new ( & ws_root. join ( "Cargo.toml" ) , config) . unwrap ( ) ;
27
+ let ws = Workspace :: new ( & ws_root. join ( "Cargo.toml" ) , config) . unwrap ( ) ;
185
28
let target_data = RustcTargetData :: new ( & ws, & requested_kinds) . unwrap ( ) ;
186
29
let cli_features = CliFeatures :: from_command_line ( & [ ] , false , true ) . unwrap ( ) ;
187
30
let pkgs = cargo:: ops:: Packages :: Default ;
@@ -212,38 +55,14 @@ fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
212
55
}
213
56
}
214
57
215
- /// Creates a new Config.
216
- ///
217
- /// This is separate from `do_resolve` to deal with the ownership and lifetime.
218
- fn make_config ( ws_root : & Path ) -> Config {
219
- let shell = cargo:: core:: Shell :: new ( ) ;
220
- let mut config = cargo:: util:: Config :: new ( shell, ws_root. to_path_buf ( ) , cargo_home ( ) ) ;
221
- // Configure is needed to set the target_dir which is needed to write
222
- // the .rustc_info.json file which is very expensive.
223
- config
224
- . configure (
225
- 0 ,
226
- false ,
227
- None ,
228
- false ,
229
- false ,
230
- false ,
231
- & Some ( target_dir ( ) ) ,
232
- & [ ] ,
233
- & [ ] ,
234
- )
235
- . unwrap ( ) ;
236
- config
237
- }
238
-
239
58
/// Benchmark of the full `resolve_ws_with_opts` which runs the resolver
240
59
/// twice, the feature resolver, and more. This is a major component of a
241
60
/// regular cargo build.
242
61
fn resolve_ws ( c : & mut Criterion ) {
243
- setup ( ) ;
62
+ let fixtures = fixtures ! ( ) ;
244
63
let mut group = c. benchmark_group ( "resolve_ws" ) ;
245
- for ( ws_name, ws_root) in workspaces ( ) {
246
- let config = make_config ( & ws_root) ;
64
+ for ( ws_name, ws_root) in fixtures . workspaces ( ) {
65
+ let config = fixtures . make_config ( & ws_root) ;
247
66
// The resolver info is initialized only once in a lazy fashion. This
248
67
// allows criterion to skip this workspace if the user passes a filter
249
68
// on the command-line (like `cargo bench -- resolve_ws/tikv`).
@@ -282,10 +101,10 @@ fn resolve_ws(c: &mut Criterion) {
282
101
283
102
/// Benchmark of the feature resolver.
284
103
fn feature_resolver ( c : & mut Criterion ) {
285
- setup ( ) ;
104
+ let fixtures = fixtures ! ( ) ;
286
105
let mut group = c. benchmark_group ( "feature_resolver" ) ;
287
- for ( ws_name, ws_root) in workspaces ( ) {
288
- let config = make_config ( & ws_root) ;
106
+ for ( ws_name, ws_root) in fixtures . workspaces ( ) {
107
+ let config = fixtures . make_config ( & ws_root) ;
289
108
let mut lazy_info = None ;
290
109
group. bench_function ( & ws_name, |b| {
291
110
let ResolveInfo {
0 commit comments