Skip to content

Commit 6d30c27

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 f58090e commit 6d30c27

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-3
lines changed

gix-pack/src/cache/delta/traverse/mod.rs

Lines changed: 3 additions & 1 deletion
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
}

gix-pack/src/cache/delta/traverse/resolve.rs

Lines changed: 8 additions & 2 deletions
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};
@@ -28,6 +28,8 @@ pub(crate) fn deltas<T, F, P, MBFN, S, E>(
2828
ItemSliceSend<Item<T>>,
2929
),
3030
hash_len: usize,
31+
_scope: &gix_features::parallel::Scope<'_, '_>,
32+
_threads_left: &AtomicIsize,
3133
should_interrupt: &AtomicBool,
3234
) -> Result<(), Error>
3335
where
@@ -105,7 +107,7 @@ where
105107
assert_eq!(
106108
base_bytes.len(),
107109
base_size as usize,
108-
"recorded base size in delta does not match"
110+
"recorded base size in delta does match the actual one"
109111
);
110112
let (result_size, consumed) = crate::data::delta::decode_header_size(&delta_bytes[consumed..]);
111113
header_ofs += consumed;
@@ -142,6 +144,10 @@ where
142144
.map(|c| c.fetch_add(base_bytes.len(), Ordering::SeqCst));
143145
}
144146
}
147+
148+
// After the first round, see if we can use additional threads, and if so we enter multi-threaded mode.
149+
// In it we will keep using new threads as they become available while using this thread for coordination.
150+
// We optimize for a low memory footprint as we are likely to get here if long delta-chains with large objects are involved.
145151
}
146152

147153
Ok(())

0 commit comments

Comments
 (0)