Skip to content

Commit ebb3999

Browse files
Try to optimize runtime by sorting the recompression list
See comment in code for details. Currently our builds see 23/48 minutes of the recompression runtime with less than full CPU utilization. The hope is that this will help cut down on that time, so that we can more efficiently make use of the available resources. If this doesn't have any effect we'll consider the FIXME in the code as well. xz compressed tarballs have metadata on the decompressed size that's not currently readable by xz2 as well, in case file length is too poor a proxy.
1 parent e04433c commit ebb3999

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ impl Context {
391391
}
392392

393393
// Generate recompressed artifacts from the input set.
394-
self.recompress(&to_recompress)?;
394+
self.recompress(to_recompress)?;
395395

396396
Ok(())
397397
}

src/recompress.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::time::Instant;
1919
use xz2::read::XzDecoder;
2020

2121
impl Context {
22-
pub fn recompress(&self, to_recompress: &[PathBuf]) -> anyhow::Result<()> {
22+
pub fn recompress(&self, mut to_recompress: Vec<PathBuf>) -> anyhow::Result<()> {
2323
println!(
2424
"starting to recompress {} files across {} threads",
2525
to_recompress.len(),
@@ -36,6 +36,19 @@ impl Context {
3636
let recompress_xz = self.config.recompress_xz;
3737
let compression_level = flate2::Compression::new(self.config.gzip_compression_level);
3838

39+
// Query the length of each file, and sort by length. This puts the smallest files
40+
// toward the end of the array, which will generally deprioritize them in the parallel
41+
// next parallel loop, avoiding as much of a long-tail on the compression work
42+
// (smallest files are fastest to recompress typically).
43+
//
44+
// FIXME: Rayon's documentation on par_iter isn't very detailed in terms of whether this
45+
// does any good. We may want to replace this with our own manual thread pool
46+
// implementation that guarantees this property - each task is large enough that just
47+
// popping from a single Mutex<Vec<...>> will be plenty fast enough.
48+
to_recompress.sort_by_cached_key(|path| {
49+
std::cmp::Reverse(fs::metadata(path).map(|m| m.len()).unwrap_or(0))
50+
});
51+
3952
to_recompress
4053
.par_iter()
4154
.map(|xz_path| {

0 commit comments

Comments
 (0)