@@ -380,14 +380,11 @@ impl Context {
380
380
Some ( "asc" ) | Some ( "sha256" ) => {
381
381
fs:: remove_file ( & path) ?;
382
382
}
383
- // Generate *.gz from *.xz.. .
383
+ // Store off the input files for potential recompression .
384
384
Some ( "xz" ) => {
385
- let gz_path = path. with_extension ( "gz" ) ;
386
- if self . config . wip_recompress || !gz_path. is_file ( ) {
387
- to_recompress. push ( ( path. to_path_buf ( ) , gz_path) ) ;
388
- }
385
+ to_recompress. push ( path. to_path_buf ( ) ) ;
389
386
}
390
- Some ( "gz" ) if self . config . wip_recompress => {
387
+ Some ( "gz" ) if self . config . recompress_gz => {
391
388
fs:: remove_file ( & path) ?;
392
389
}
393
390
_ => { }
@@ -404,19 +401,76 @@ impl Context {
404
401
to_recompress. len( ) ,
405
402
to_recompress. len( ) . min( rayon:: current_num_threads( ) ) ,
406
403
) ;
404
+ println ! ( "gzip recompression enabled: {}" , self . config. recompress_gz) ;
405
+ println ! ( "xz recompression enabled: {}" , self . config. recompress_xz) ;
407
406
let recompress_start = Instant :: now ( ) ;
408
407
408
+ let recompress_gz = self . config . recompress_gz ;
409
+ let recompress_xz = self . config . recompress_xz ;
409
410
let compression_level = flate2:: Compression :: new ( self . config . gzip_compression_level ) ;
410
411
to_recompress
411
412
. par_iter ( )
412
- . map ( |( xz_path, gz_path) | {
413
- println ! ( "recompressing {}..." , gz_path. display( ) ) ;
414
-
415
- let xz = File :: open ( xz_path) ?;
416
- let mut xz = XzDecoder :: new ( xz) ;
417
- let gz = File :: create ( gz_path) ?;
418
- let mut gz = flate2:: write:: GzEncoder :: new ( gz, compression_level) ;
419
- io:: copy ( & mut xz, & mut gz) ?;
413
+ . map ( |xz_path| {
414
+ println ! ( "recompressing {}..." , xz_path. display( ) ) ;
415
+ let gz_path = xz_path. with_extension ( "gz" ) ;
416
+
417
+ // Produce gzip if explicitly enabled or the destination file doesn't exist.
418
+ if recompress_gz || !gz_path. is_file ( ) {
419
+ let mut xz_orig = XzDecoder :: new ( File :: open ( xz_path) ?) ;
420
+ let gz = File :: create ( gz_path) ?;
421
+ let mut gz = flate2:: write:: GzEncoder :: new ( gz, compression_level) ;
422
+ io:: copy ( & mut xz_orig, & mut gz) ?;
423
+ }
424
+
425
+ // xz recompression with more aggressive settings than we want to take the time
426
+ // for in rust-lang/rust CI. This cuts 5-15% off of the produced tarballs.
427
+ //
428
+ // Note that this is using a single-threaded compressor as we're parallelizing
429
+ // via rayon already. In rust-lang/rust we were trying to use parallel
430
+ // compression, but the default block size for that is 3*dict_size so we
431
+ // weren't actually using more than one core in most of the builders with
432
+ // <192MB uncompressed tarballs. In promote-release since we're recompressing
433
+ // 100s of tarballs there's no need for each individual compression to be
434
+ // parallel.
435
+ if recompress_xz {
436
+ let mut filters = xz2:: stream:: Filters :: new ( ) ;
437
+ let mut lzma_ops = xz2:: stream:: LzmaOptions :: new_preset ( 9 ) . unwrap ( ) ;
438
+ // This sets the overall dictionary size, which is also how much memory (baseline)
439
+ // is needed for decompression.
440
+ lzma_ops. dict_size ( 64 * 1024 * 1024 ) ;
441
+ // Use the best match finder for compression ratio.
442
+ lzma_ops. match_finder ( xz2:: stream:: MatchFinder :: BinaryTree4 ) ;
443
+ lzma_ops. mode ( xz2:: stream:: Mode :: Normal ) ;
444
+ // Set nice len to the maximum for best compression ratio
445
+ lzma_ops. nice_len ( 273 ) ;
446
+ // Set depth to a reasonable value, 0 means auto, 1000 is somwhat high but gives
447
+ // good results.
448
+ lzma_ops. depth ( 1000 ) ;
449
+ // 2 is the default and does well for most files
450
+ lzma_ops. position_bits ( 2 ) ;
451
+ // 0 is the default and does well for most files
452
+ lzma_ops. literal_position_bits ( 0 ) ;
453
+ // 3 is the default and does well for most files
454
+ lzma_ops. literal_context_bits ( 3 ) ;
455
+
456
+ filters. lzma2 ( & lzma_ops) ;
457
+
458
+ // FIXME: Do we want a checksum as part of compression?
459
+ let stream = xz2:: stream:: Stream :: new_stream_encoder (
460
+ & filters,
461
+ xz2:: stream:: Check :: None ,
462
+ )
463
+ . unwrap ( ) ;
464
+ let xz_recompressed = xz_path. with_extension ( "xz_recompressed" ) ;
465
+ let xz_out = File :: create ( & xz_recompressed) ?;
466
+ let mut xz_out = xz2:: write:: XzEncoder :: new_stream (
467
+ std:: io:: BufWriter :: new ( xz_out) ,
468
+ stream,
469
+ ) ;
470
+ let mut xz_orig = XzDecoder :: new ( File :: open ( xz_path) ?) ;
471
+ io:: copy ( & mut xz_orig, & mut xz_out) ?;
472
+ fs:: rename ( & xz_recompressed, & xz_path) ?;
473
+ }
420
474
421
475
Ok :: < ( ) , Error > ( ( ) )
422
476
} )
0 commit comments