History

Try to use counters directly in delta-tree resolution

However, it seems slightly slower and doesn't necessarily improve the progress printing. Also, we have ot content over two counters, not only one, which might be noticable and is probably not worth it.

Sebastian Thiel committed 4 years ago

Commit c6ded261 parent ff1db662 files · +50 −51Browse files

Unified · Split

2 files
  1. git-pack/src/cache/delta/traverse/mod.rs +37 −41
  2. git-pack/src/cache/delta/traverse/resolve.rs +13 −10
git-pack/src/cache/delta/traverse/mod.rs+37−41
@@ -108,7 +108,7 @@ where · 107 unmodified lines
108 Options {108 Options {
109 thread_limit,109 thread_limit,
110 object_progress,110 object_progress,
111 size_progress,111 mut size_progress,
112 should_interrupt,112 should_interrupt,
113 object_hash,113 object_hash,
114 }: Options<'_, P1, P2>,114 }: Options<'_, P1, P2>,
@@ -128,6 +128,16 @@ where · 13 unmodified lines
128 // allowing threads to be more busy overall. This, however, needs some refactorings to allow operation128 // allowing threads to be more busy overall. This, however, needs some refactorings to allow operation
129 // on a single item efficiently while providing real-time feedback.129 // on a single item efficiently while providing real-time feedback.
130 let num_objects = self.num_items();130 let num_objects = self.num_items();
131
132 let object_counter = {
133 let mut progress = lock(&object_progress);
134 progress.init(Some(num_objects), progress::count("objects"));
135 progress.counter()
136 };
137 size_progress.init(None, progress::bytes());
138 let size_counter = size_progress.counter();
139
140 let start = std::time::Instant::now();
131 in_parallel_if(141 in_parallel_if(
132 should_run_in_parallel,142 should_run_in_parallel,
133 self.iter_root_chunks(chunk_size),143 self.iter_root_chunks(chunk_size),
@@ -144,9 +154,25 @@ where · 10 unmodified lines
144 )154 )
145 }155 }
146 },156 },
147 move |root_nodes, state| resolve::deltas(root_nodes, state, object_hash.len_in_bytes()),157 {
148 Reducer::new(num_objects, object_progress, size_progress, should_interrupt),158 let object_counter = object_counter.clone();
159 let size_counter = size_counter.clone();
160 move |root_nodes, state| {
161 resolve::deltas(
162 object_counter.clone(),
163 size_counter.clone(),
164 root_nodes,
165 state,
166 object_hash.len_in_bytes(),
167 )
168 }
169 },
170 Reducer::new(should_interrupt),
149 )?;171 )?;
172
173 lock(&object_progress).show_throughput(start);
174 size_progress.show_throughput(start);
175
150 Ok(Outcome {176 Ok(Outcome {
151 roots: self.root_items,177 roots: self.root_items,
152 children: self.child_items,178 children: self.child_items,
@@ -154,61 +180,31 @@ where · 1 unmodified line
154 }180 }
155}181}
156 182
157struct Reducer<'a, P1, P2> {183struct Reducer<'a> {
158 item_count: usize,
159 progress: OwnShared<Mutable<P1>>,
160 start: std::time::Instant,
161 size_progress: P2,
162 should_interrupt: &'a AtomicBool,184 should_interrupt: &'a AtomicBool,
163}185}
164 186
165impl<'a, P1, P2> Reducer<'a, P1, P2>187impl<'a> Reducer<'a> {
166where188 pub fn new(should_interrupt: &'a AtomicBool) -> Self {
167 P1: Progress,189 Reducer { should_interrupt }
168 P2: Progress,
169{
170 pub fn new(
171 num_objects: usize,
172 progress: OwnShared<Mutable<P1>>,
173 mut size_progress: P2,
174 should_interrupt: &'a AtomicBool,
175 ) -> Self {
176 lock(&progress).init(Some(num_objects), progress::count("objects"));
177 size_progress.init(None, progress::bytes());
178 Reducer {
179 item_count: 0,
180 progress,
181 start: std::time::Instant::now(),
182 size_progress,
183 should_interrupt,
184 }
185 }190 }
186}191}
187 192
188impl<'a, P1, P2> parallel::Reduce for Reducer<'a, P1, P2>193impl<'a> parallel::Reduce for Reducer<'a> {
189where194 type Input = Result<(), Error>;
190 P1: Progress,
191 P2: Progress,
192{
193 type Input = Result<(usize, u64), Error>;
194 type FeedProduce = ();195 type FeedProduce = ();
195 type Output = ();196 type Output = ();
196 type Error = Error;197 type Error = Error;
197 198
198 fn feed(&mut self, input: Self::Input) -> Result<(), Self::Error> {199 fn feed(&mut self, input: Self::Input) -> Result<(), Self::Error> {
199 let (num_objects, decompressed_size) = input?;200 input?;
200 self.item_count += num_objects;
201 self.size_progress.inc_by(decompressed_size as usize);
202 lock(&self.progress).set(self.item_count);
203 if self.should_interrupt.load(Ordering::SeqCst) {201 if self.should_interrupt.load(Ordering::SeqCst) {
204 return Err(Error::Interrupted);202 return Err(Error::Interrupted);
205 }203 }
206 Ok(())204 Ok(())
207 }205 }
208 206
209 fn finalize(mut self) -> Result<Self::Output, Self::Error> {207 fn finalize(self) -> Result<Self::Output, Self::Error> {
210 lock(&self.progress).show_throughput(self.start);
211 self.size_progress.show_throughput(self.start);
212 Ok(())208 Ok(())
213 }209 }
214}210}
git-pack/src/cache/delta/traverse/resolve.rs+13−10
@@ -1,3 +1,4 @@
1use std::sync::atomic::Ordering;
1use std::{cell::RefCell, collections::BTreeMap};2use std::{cell::RefCell, collections::BTreeMap};
2 3
3use git_features::{4use git_features::{
@@ -11,10 +12,12 @@ use crate::{ · 7 unmodified lines
11};12};
12 13
13pub(crate) fn deltas<T, F, P, MBFN, S, E>(14pub(crate) fn deltas<T, F, P, MBFN, S, E>(
15 object_counter: Option<git_features::progress::StepShared>,
16 size_counter: Option<git_features::progress::StepShared>,
14 nodes: crate::cache::delta::Chunk<'_, T>,17 nodes: crate::cache::delta::Chunk<'_, T>,
15 (bytes_buf, ref mut progress, state, resolve, modify_base): &mut (Vec<u8>, P, S, F, MBFN),18 (bytes_buf, ref mut progress, state, resolve, modify_base): &mut (Vec<u8>, P, S, F, MBFN),
16 hash_len: usize,19 hash_len: usize,
17) -> Result<(usize, u64), Error>20) -> Result<(), Error>
18where21where
19 F: for<'r> Fn(EntryRange, &'r mut Vec<u8>) -> Option<()>,22 F: for<'r> Fn(EntryRange, &'r mut Vec<u8>) -> Option<()>,
20 P: Progress,23 P: Progress,
@@ -23,8 +26,6 @@ where · 2 unmodified lines
23{26{
24 let mut decompressed_bytes_by_pack_offset = BTreeMap::new();27 let mut decompressed_bytes_by_pack_offset = BTreeMap::new();
25 let bytes_buf = RefCell::new(bytes_buf);28 let bytes_buf = RefCell::new(bytes_buf);
26 let mut num_objects = 0;
27 let mut decompressed_bytes: u64 = 0;
28 let decompress_from_resolver = |slice: EntryRange| -> Result<(crate::data::Entry, u64, Vec<u8>), Error> {29 let decompress_from_resolver = |slice: EntryRange| -> Result<(crate::data::Entry, u64, Vec<u8>), Error> {
29 let mut bytes_buf = bytes_buf.borrow_mut();30 let mut bytes_buf = bytes_buf.borrow_mut();
30 bytes_buf.resize((slice.end - slice.start) as usize, 0);31 bytes_buf.resize((slice.end - slice.start) as usize, 0);
@@ -75,9 +76,10 @@ where · 44 unmodified lines
75 },76 },
76 )77 )
77 .map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync>)?;78 .map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync>)?;
78 num_objects += 1;79 object_counter.as_ref().map(|c| c.fetch_add(1, Ordering::SeqCst));
79 decompressed_bytes += base_bytes.len() as u64;80 size_counter
80 progress.inc();81 .as_ref()
82 .map(|c| c.fetch_add(base_bytes.len(), Ordering::SeqCst));
81 }83 }
82 84
83 for mut child in base.into_child_iter() {85 for mut child in base.into_child_iter() {
@@ -118,14 +120,15 @@ where · 34 unmodified lines
118 },120 },
119 )121 )
120 .map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync>)?;122 .map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync>)?;
121 num_objects += 1;123 object_counter.as_ref().map(|c| c.fetch_add(1, Ordering::SeqCst));
122 decompressed_bytes += fully_resolved_delta_bytes.len() as u64;124 size_counter
123 progress.inc();125 .as_ref()
126 .map(|c| c.fetch_add(base_bytes.len(), Ordering::SeqCst));
124 }127 }
125 }128 }
126 }129 }
127 130
128 Ok((num_objects, decompressed_bytes))131 Ok(())
129}132}
130 133
131fn decompress_all_at_once(b: &[u8], decompressed_len: usize) -> Result<Vec<u8>, Error> {134fn decompress_all_at_once(b: &[u8], decompressed_len: usize) -> Result<Vec<u8>, Error> {