Split remaining delta work on path boundaries
When an idle thread tries to steal work from a sibling's remaining toSearch queue, always try to split along a path boundary. This avoids missing delta opportunities in the current window of the thread whose work is being taken. The search order is reversed to walk further down the chain from current position, avoiding the risk of splitting the list within the path the thread is currently processing. When selecting which thread to split from use an accurate estimate of the size to be taken. This avoids selecting a thread that has only one path remaining but may contain more pending entries than another thread with several paths remaining. As there is now a race condition where the straggling thread can start the next path before the split can finish, the stealWork() loop spins until it is able to acquire a split or there is only one path remaining in the siblings. Change-Id: Ib11ff99f90a4d9efab24bf4a85342cc63203dba5
This commit is contained in:
parent
af33a911d0
commit
3b7924f403
|
@ -76,23 +76,24 @@ static final class Block {
|
|||
}
|
||||
|
||||
synchronized Slice stealWork() {
|
||||
for (int attempts = 0; attempts < 2; attempts++) {
|
||||
for (;;) {
|
||||
DeltaTask maxTask = null;
|
||||
Slice maxSlice = null;
|
||||
int maxWork = 0;
|
||||
|
||||
for (DeltaTask task : tasks) {
|
||||
int r = task.remaining();
|
||||
if (maxWork < r) {
|
||||
Slice s = task.remaining();
|
||||
if (s != null && maxWork < s.size()) {
|
||||
maxTask = task;
|
||||
maxWork = r;
|
||||
maxSlice = s;
|
||||
maxWork = s.size();
|
||||
}
|
||||
}
|
||||
if (maxTask == null)
|
||||
return null;
|
||||
Slice s = maxTask.stealWork();
|
||||
if (s != null)
|
||||
return s;
|
||||
if (maxTask.tryStealWork(maxSlice))
|
||||
return maxSlice;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +105,10 @@ static final class Slice {
|
|||
beginIndex = b;
|
||||
endIndex = e;
|
||||
}
|
||||
|
||||
final int size() {
|
||||
return endIndex - beginIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private final Block block;
|
||||
|
@ -131,13 +136,13 @@ public Object call() throws Exception {
|
|||
return null;
|
||||
}
|
||||
|
||||
int remaining() {
|
||||
Slice remaining() {
|
||||
DeltaWindow d = dw;
|
||||
return d != null ? d.remaining() : 0;
|
||||
return d != null ? d.remaining() : null;
|
||||
}
|
||||
|
||||
Slice stealWork() {
|
||||
boolean tryStealWork(Slice s) {
|
||||
DeltaWindow d = dw;
|
||||
return d != null ? d.stealWork() : null;
|
||||
return d != null ? d.tryStealWork(s) : false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,26 +115,37 @@ final class DeltaWindow {
|
|||
res = DeltaWindowEntry.createWindow(config.getDeltaSearchWindowSize());
|
||||
}
|
||||
|
||||
synchronized int remaining() {
|
||||
return end - cur;
|
||||
}
|
||||
|
||||
synchronized DeltaTask.Slice stealWork() {
|
||||
synchronized DeltaTask.Slice remaining() {
|
||||
int e = end;
|
||||
int n = (e - cur) >>> 1;
|
||||
if (0 == n)
|
||||
int halfRemaining = (e - cur) >>> 1;
|
||||
if (0 == halfRemaining)
|
||||
return null;
|
||||
|
||||
int t = e - n;
|
||||
int h = toSearch[t].getPathHash();
|
||||
while (cur < t) {
|
||||
if (h == toSearch[t - 1].getPathHash())
|
||||
t--;
|
||||
else
|
||||
break;
|
||||
int split = e - halfRemaining;
|
||||
int h = toSearch[split].getPathHash();
|
||||
|
||||
// Attempt to split on the next path after the 50% split point.
|
||||
for (int n = split + 1; n < e; n++) {
|
||||
if (h != toSearch[n].getPathHash())
|
||||
return new DeltaTask.Slice(n, e);
|
||||
}
|
||||
end = t;
|
||||
return new DeltaTask.Slice(t, e);
|
||||
|
||||
if (h != toSearch[cur].getPathHash()) {
|
||||
// Try to split on the path before the 50% split point.
|
||||
// Do not split the path currently being processed.
|
||||
for (int p = split - 1; cur < p; p--) {
|
||||
if (h != toSearch[p].getPathHash())
|
||||
return new DeltaTask.Slice(p + 1, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized boolean tryStealWork(DeltaTask.Slice s) {
|
||||
if (s.beginIndex <= cur)
|
||||
return false;
|
||||
end = s.beginIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
void search() throws IOException {
|
||||
|
|
Loading…
Reference in New Issue