gerrit: a bad implementation of parallel object finding

This commit is contained in:
Luke Granger-Brown 2024-07-08 21:56:31 +01:00
parent 23dd318e67
commit 1d7704d247
2 changed files with 64 additions and 0 deletions

View file

@ -47,6 +47,8 @@ in
./gerrit-cl-431977-bump-sshd.patch ./gerrit-cl-431977-bump-sshd.patch
./gerrit-cl-431977-part-2-bump-bouncycastle.patch ./gerrit-cl-431977-part-2-bump-bouncycastle.patch
./jgit-parallel-object-counting.patch
]; ];
nativeBuildInputs = [ nativeBuildInputs = [

View file

@ -0,0 +1,62 @@
diff --git a/modules/jgit/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java b/modules/jgit/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java
index 01f514b93..c9888657a 100644
--- a/modules/jgit/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java
+++ b/modules/jgit/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java
@@ -18,6 +18,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
@@ -166,10 +167,49 @@ public LocalObjectToPack newObjectToPack(AnyObjectId objectId, int type) {
return new LocalObjectToPack(objectId, type);
}
+ /* Above this number of objects, perform this counting in parallel. */
+ private static final int OBJECTS_TO_MULTITHREAD = 10_000;
+
@Override
public void selectObjectRepresentation(PackWriter packer,
ProgressMonitor monitor, Iterable<ObjectToPack> objects)
throws IOException, MissingObjectException {
+ if (objects instanceof Collection<ObjectToPack>) {
+ // If it isn't a collection, we can't tell how many objects there are.
+ Collection<ObjectToPack> sizedObjects = (Collection<ObjectToPack>)objects;
+ if (sizedObjects.size() >= OBJECTS_TO_MULTITHREAD) {
+ // Where we're going, we don't need single-threaded.
+ AtomicInteger counter = new AtomicInteger();
+ try {
+ sizedObjects.parallelStream()
+ .forEach(otp -> {
+ try {
+ // TODO: maybe creating a new WindowCursor each time is expensive?
+ db.selectObjectRepresentation(packer, otp, new WindowCursor(db));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ if (counter.incrementAndGet() >= OBJECTS_TO_MULTITHREAD) {
+ int rem = counter.getAndSet(0);
+ if (rem >= OBJECTS_TO_MULTITHREAD) {
+ synchronized (monitor) {
+ monitor.update(rem);
+ }
+ } else {
+ counter.addAndGet(rem);
+ }
+ }
+ });
+ monitor.update(counter.get());
+ } catch (RuntimeException e) {
+ if (e.getCause() != null && e.getCause() instanceof IOException) throw (IOException)e.getCause();
+ throw e;
+ }
+ return;
+ }
+ }
+
+ // Otherwise, single-threaded mode.
for (ObjectToPack otp : objects) {
db.selectObjectRepresentation(packer, otp, this);
monitor.update(1);