Mercurial > hg
comparison rust/hg-core/src/revlog/inner_revlog.rs @ 52308:7756494c5ecd
rust-inner-revlog: cache the compressor
The `compress` function is unlikely to be used in highly contended situations,
and creating a compressor has some overhead, on top of losing out on some
potential advantages of longer-running optimizations from the compressor.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 04 Nov 2024 12:10:22 +0100 |
parents | 7ffc71552662 |
children | f69a3f55fa9b |
comparison
equal
deleted
inserted
replaced
52307:22d24f6d6411 | 52308:7756494c5ecd |
---|---|
50 /// Data config that applies to this revlog | 50 /// Data config that applies to this revlog |
51 data_config: RevlogDataConfig, | 51 data_config: RevlogDataConfig, |
52 /// Delta config that applies to this revlog | 52 /// Delta config that applies to this revlog |
53 delta_config: RevlogDeltaConfig, | 53 delta_config: RevlogDeltaConfig, |
54 /// Feature config that applies to this revlog | 54 /// Feature config that applies to this revlog |
55 #[allow(unused)] | |
55 feature_config: RevlogFeatureConfig, | 56 feature_config: RevlogFeatureConfig, |
56 /// A view into this revlog's data file | 57 /// A view into this revlog's data file |
57 segment_file: RandomAccessFile, | 58 segment_file: RandomAccessFile, |
58 /// A cache of uncompressed chunks that have previously been restored. | 59 /// A cache of uncompressed chunks that have previously been restored. |
59 /// Its eviction policy is defined in [`Self::new`]. | 60 /// Its eviction policy is defined in [`Self::new`]. |
69 /// Whether this revlog is inline. XXX why duplicate from `index`? | 70 /// Whether this revlog is inline. XXX why duplicate from `index`? |
70 pub inline: bool, | 71 pub inline: bool, |
71 /// A cache of the last revision, which is usually accessed multiple | 72 /// A cache of the last revision, which is usually accessed multiple |
72 /// times. | 73 /// times. |
73 pub last_revision_cache: Mutex<Option<SingleRevisionCache>>, | 74 pub last_revision_cache: Mutex<Option<SingleRevisionCache>>, |
75 /// The [`Compressor`] that this revlog uses by default to compress data. | |
76 /// This does not mean that this revlog uses this compressor for reading | |
77 /// data, as different revisions may have different compression modes. | |
78 compressor: Mutex<Box<dyn Compressor + Send>>, | |
74 } | 79 } |
75 | 80 |
76 impl InnerRevlog { | 81 impl InnerRevlog { |
77 pub fn new( | 82 pub fn new( |
78 vfs: Box<dyn Vfs>, | 83 vfs: Box<dyn Vfs>, |
115 original_index_file: None, | 120 original_index_file: None, |
116 writing_handles: None, | 121 writing_handles: None, |
117 delayed_buffer: None, | 122 delayed_buffer: None, |
118 inline, | 123 inline, |
119 last_revision_cache: Mutex::new(None), | 124 last_revision_cache: Mutex::new(None), |
125 compressor: Mutex::new(match feature_config.compression_engine { | |
126 CompressionConfig::Zlib { level } => { | |
127 Box::new(ZlibCompressor::new(level)) | |
128 } | |
129 CompressionConfig::Zstd { level, threads } => { | |
130 Box::new(ZstdCompressor::new(level, threads)) | |
131 } | |
132 CompressionConfig::None => Box::new(NoneCompressor), | |
133 }), | |
120 } | 134 } |
121 } | 135 } |
122 | 136 |
123 /// Return number of entries of the revlog index | 137 /// Return number of entries of the revlog index |
124 pub fn len(&self) -> usize { | 138 pub fn len(&self) -> usize { |
284 stop_rev, | 298 stop_rev, |
285 self.delta_config.general_delta.into(), | 299 self.delta_config.general_delta.into(), |
286 ) | 300 ) |
287 } | 301 } |
288 | 302 |
289 fn compressor(&self) -> Result<Box<dyn Compressor>, HgError> { | |
290 // TODO cache the compressor? | |
291 Ok(match self.feature_config.compression_engine { | |
292 CompressionConfig::Zlib { level } => { | |
293 Box::new(ZlibCompressor::new(level)) | |
294 } | |
295 CompressionConfig::Zstd { level, threads } => { | |
296 Box::new(ZstdCompressor::new(level, threads)) | |
297 } | |
298 CompressionConfig::None => Box::new(NoneCompressor), | |
299 }) | |
300 } | |
301 | |
302 /// Generate a possibly-compressed representation of data. | 303 /// Generate a possibly-compressed representation of data. |
303 /// Returns `None` if the data was not compressed. | 304 /// Returns `None` if the data was not compressed. |
304 pub fn compress<'data>( | 305 pub fn compress<'data>( |
305 &self, | 306 &self, |
306 data: &'data [u8], | 307 data: &'data [u8], |
307 ) -> Result<Option<Cow<'data, [u8]>>, RevlogError> { | 308 ) -> Result<Option<Cow<'data, [u8]>>, RevlogError> { |
308 if data.is_empty() { | 309 if data.is_empty() { |
309 return Ok(Some(data.into())); | 310 return Ok(Some(data.into())); |
310 } | 311 } |
311 let res = self.compressor()?.compress(data)?; | 312 let res = self.compressor.lock().unwrap().compress(data)?; |
312 if let Some(compressed) = res { | 313 if let Some(compressed) = res { |
313 // The revlog compressor added the header in the returned data. | 314 // The revlog compressor added the header in the returned data. |
314 return Ok(Some(compressed.into())); | 315 return Ok(Some(compressed.into())); |
315 } | 316 } |
316 | 317 |