comparison rust/hg-core/src/revlog/mod.rs @ 50508:39ed7b2953bb

rust: mostly avoid streaming zstd decompression Streaming ZStd decompression seems slightly slower, and the API we use makes it very inconvenient to re-use the decompression context. Instead of using that, use the buffer-backed version, because we can give a reasonable-ish size estimate.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Thu, 18 May 2023 17:53:17 +0100
parents d1cab48354bc
children 0159b014f3ab
comparison
equal deleted inserted replaced
50507:d1cab48354bc 50508:39ed7b2953bb
594 Ok(buf) 594 Ok(buf)
595 } 595 }
596 } 596 }
597 597
598 fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> { 598 fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> {
599 let cap = self.uncompressed_len.max(0) as usize;
599 if self.is_delta() { 600 if self.is_delta() {
600 let mut buf = Vec::with_capacity(self.compressed_len as usize); 601 // [cap] is usually an over-estimate of the space needed because
601 zstd::stream::copy_decode(self.bytes, &mut buf) 602 // it's the length of delta-decoded data, but we're interested
602 .map_err(|e| corrupted(e.to_string()))?; 603 // in the size of the delta.
604 // This means we have to [shrink_to_fit] to avoid holding on
605 // to a large chunk of memory, but it also means we must have a
606 // fallback branch, for the case when the delta is longer than
607 // the original data (surprisingly, this does happen in practice)
608 let mut buf = Vec::with_capacity(cap);
609 match zstd_decompress_to_buffer(self.bytes, &mut buf) {
610 Ok(_) => buf.shrink_to_fit(),
611 Err(_) => {
612 buf.clear();
613 zstd::stream::copy_decode(self.bytes, &mut buf)
614 .map_err(|e| corrupted(e.to_string()))?;
615 }
616 };
603 Ok(buf) 617 Ok(buf)
604 } else { 618 } else {
605 let cap = self.uncompressed_len.max(0) as usize;
606 let mut buf = Vec::with_capacity(cap); 619 let mut buf = Vec::with_capacity(cap);
607 let len = zstd_decompress_to_buffer(self.bytes, &mut buf) 620 let len = zstd_decompress_to_buffer(self.bytes, &mut buf)
608 .map_err(|e| corrupted(e.to_string()))?; 621 .map_err(|e| corrupted(e.to_string()))?;
609 if len != self.uncompressed_len as usize { 622 if len != self.uncompressed_len as usize {
610 Err(corrupted("uncompressed length does not match")) 623 Err(corrupted("uncompressed length does not match"))