Skip to content

Commit ff1f3b3

Browse files
committed
feat: index-backed tree traversal with a form of work-stealing. (#851)
When delta-trees are unbalanced, in pathological cases it's possible that that one thread ends up with more than half of the work. In this case it's required that it manages to spawn its own threads to parallelize the work it has.
1 parent 203a064 commit ff1f3b3

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-3
lines changed

Diff for: gix-pack/src/cache/delta/traverse/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,15 @@ where
152152
}
153153
},
154154
{
155-
move |node, state, _scope, _threads_left, should_interrupt| {
155+
move |node, state, scope, threads_left, should_interrupt| {
156156
resolve::deltas(
157157
object_counter.clone(),
158158
size_counter.clone(),
159159
node,
160160
state,
161161
object_hash.len_in_bytes(),
162+
scope,
163+
threads_left,
162164
should_interrupt,
163165
)
164166
}

Diff for: gix-pack/src/cache/delta/traverse/resolve.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::sync::atomic::AtomicBool;
1+
use std::sync::atomic::{AtomicBool, AtomicIsize};
22
use std::{cell::RefCell, collections::BTreeMap, sync::atomic::Ordering};
33

44
use gix_features::{progress::Progress, zlib};
@@ -27,6 +27,8 @@ pub(crate) fn deltas<T, F, P, MBFN, S, E>(
2727
ItemSliceSend<Item<T>>,
2828
),
2929
hash_len: usize,
30+
_scope: &gix_features::parallel::Scope<'_, '_>,
31+
_threads_left: &AtomicIsize,
3032
should_interrupt: &AtomicBool,
3133
) -> Result<(), Error>
3234
where
@@ -104,7 +106,7 @@ where
104106
assert_eq!(
105107
base_bytes.len(),
106108
base_size as usize,
107-
"recorded base size in delta does not match"
109+
"recorded base size in delta does match the actual one"
108110
);
109111
let (result_size, consumed) = crate::data::delta::decode_header_size(&delta_bytes[consumed..]);
110112
header_ofs += consumed;
@@ -141,6 +143,10 @@ where
141143
.map(|c| c.fetch_add(base_bytes.len(), Ordering::SeqCst));
142144
}
143145
}
146+
147+
// After the first round, see if we can use additional threads, and if so we enter multi-threaded mode.
148+
// In it we will keep using new threads as they become available while using this thread for coordination.
149+
// We optimize for a low memory footprint as we are likely to get here if long delta-chains with large objects are involved.
144150
}
145151

146152
Ok(())

0 commit comments

Comments
 (0)