@@ -11,6 +11,7 @@ use crate::utils::notifications::Notification;
11
11
use crate :: utils:: utils;
12
12
13
13
use std:: collections:: HashSet ;
14
+ use std:: env;
14
15
use std:: fmt;
15
16
use std:: io:: Read ;
16
17
use std:: path:: { Path , PathBuf } ;
@@ -214,8 +215,11 @@ impl<'a> TarPackage<'a> {
214
215
}
215
216
}
216
217
217
- #[ cfg( windows) ]
218
- mod unpacker {
218
+ trait Unpacker {
219
+ fn handle ( & mut self , unpacked : tar:: Unpacked ) ;
220
+ }
221
+
222
+ mod threadedunpacker {
219
223
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
220
224
use std:: sync:: Arc ;
221
225
use threadpool;
@@ -239,12 +243,33 @@ mod unpacker {
239
243
. build ( ) ;
240
244
Unpacker {
241
245
n_files : Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
242
- pool : pool ,
243
- notify_handler : notify_handler ,
246
+ pool,
247
+ notify_handler,
244
248
}
245
249
}
246
250
247
- pub fn handle ( & mut self , unpacked : tar:: Unpacked ) {
251
+ pub fn new_with_threads (
252
+ notify_handler : Option < & ' a dyn Fn ( Notification < ' _ > ) > ,
253
+ thread_count : usize ,
254
+ ) -> Self {
255
+ // Defaults to hardware thread count threads; this is suitable for
256
+ // our needs as IO bound operations tend to show up as write latencies
257
+ // rather than close latencies, so we don't need to look at
258
+ // more threads to get more IO dispatched at this stage in the process.
259
+ let pool = threadpool:: Builder :: new ( )
260
+ . thread_name ( "CloseHandle" . into ( ) )
261
+ . num_threads ( thread_count)
262
+ . build ( ) ;
263
+ Unpacker {
264
+ n_files : Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
265
+ pool,
266
+ notify_handler,
267
+ }
268
+ }
269
+ }
270
+
271
+ impl < ' a > super :: Unpacker for Unpacker < ' a > {
272
+ fn handle ( & mut self , unpacked : tar:: Unpacked ) {
248
273
if let tar:: Unpacked :: File ( f) = unpacked {
249
274
self . n_files . fetch_add ( 1 , Ordering :: Relaxed ) ;
250
275
let n_files = self . n_files . clone ( ) ;
@@ -307,15 +332,16 @@ mod unpacker {
307
332
}
308
333
}
309
334
310
- #[ cfg( not( windows) ) ]
311
335
mod unpacker {
312
336
use crate :: utils:: notifications:: Notification ;
313
337
pub struct Unpacker { }
314
338
impl Unpacker {
315
339
pub fn new < ' a > ( _notify_handler : Option < & ' a dyn Fn ( Notification < ' _ > ) > ) -> Unpacker {
316
340
Unpacker { }
317
341
}
318
- pub fn handle ( & mut self , _unpacked : tar:: Unpacked ) { }
342
+ }
343
+ impl super :: Unpacker for Unpacker {
344
+ fn handle ( & mut self , _unpacked : tar:: Unpacked ) { }
319
345
}
320
346
}
321
347
@@ -324,7 +350,22 @@ fn unpack_without_first_dir<'a, R: Read>(
324
350
path : & Path ,
325
351
notify_handler : Option < & ' a dyn Fn ( Notification < ' _ > ) > ,
326
352
) -> Result < ( ) > {
327
- let mut unpacker = unpacker:: Unpacker :: new ( notify_handler) ;
353
+ let mut unpacker : Box < dyn Unpacker > =
354
+ // If this gets lots of use, consider exposing via the config file.
355
+ if let Ok ( thread_str) = env:: var ( "RUSTUP_CLOSE_THREADS" ) {
356
+ if thread_str == "disabled" {
357
+ Box :: new ( unpacker:: Unpacker :: new ( notify_handler) )
358
+ } else {
359
+ if let Ok ( thread_count) = thread_str. parse :: < usize > ( ) {
360
+ Box :: new ( threadedunpacker:: Unpacker :: new_with_threads ( notify_handler, thread_count) )
361
+ } else {
362
+ Box :: new ( threadedunpacker:: Unpacker :: new ( notify_handler) )
363
+ }
364
+ }
365
+ } else {
366
+ Box :: new ( threadedunpacker:: Unpacker :: new ( notify_handler) )
367
+ }
368
+ ;
328
369
let entries = archive
329
370
. entries ( )
330
371
. chain_err ( || ErrorKind :: ExtractingPackage ) ?;
0 commit comments