aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src
diff options
context:
space:
mode:
authorMartin Fick <mfick@nvidia.com>2024-11-27 10:15:30 -0800
committerMartin Fick <mfick@nvidia.com>2024-12-02 23:29:44 +0000
commit44d61a3d727eb68db9e57acec0704bfc6758f878 (patch)
tree27ffa6eecd5b0d8106f332dcb25ed09d9f0fbcd0 /org.eclipse.jgit/src
parent702db13af2b96c0f699fa6be0a63ba281535f337 (diff)
downloadjgit-44d61a3d727eb68db9e57acec0704bfc6758f878.tar.gz
jgit-44d61a3d727eb68db9e57acec0704bfc6758f878.zip
WindowCache: add bulk purge(), call from bulk sites
Purging a Pack from the WindowCache requires a linear search over all the entries in the cache, and thus is rather expensive. Since git gc often deletes more than one packfile at a time, avoid multiplying this expensive operation when possible by purging a Set of Packs when closing deleted pack files during a directory scan. Purge the Set of Packs with a single linear search of the cache. Closing the PackDirectory also cccbngljkihltghcnbiftcubdvgugdcvujkejehbjr Change-Id: Ic9b45cab57e1ef610c2e20ad392d8b45f8091f41 Signed-off-by: Martin Fick <mfick@nvidia.com>
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java25
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java24
3 files changed, 37 insertions, 21 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java
index 3518342f97..9073c1675a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java
@@ -296,15 +296,28 @@ public class Pack implements Iterable<PackIndex.MutableEntry> {
}
/**
- * Close the resources utilized by this repository
+ * Close the resources utilized by these pack files
+ *
+ * @param packs
+ * packs to close
+ */
+ public static void close(Set<Pack> packs) {
+ WindowCache.purge(packs);
+ packs.forEach(p -> p.closeIndices());
+ }
+
+ /**
+ * Close the resources utilized by this pack file
*/
public void close() {
WindowCache.purge(this);
- synchronized (this) {
- loadedIdx.clear();
- reverseIdx.clear();
- bitmapIdx.clear();
- }
+ closeIndices();
+ }
+
+ private synchronized void closeIndices() {
+ loadedIdx.clear();
+ reverseIdx.clear();
+ bitmapIdx.clear();
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
index 51a8148838..e31126f027 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -111,9 +112,7 @@ class PackDirectory {
void close() {
PackList packs = packList.get();
if (packs != NO_PACKS && packList.compareAndSet(packs, NO_PACKS)) {
- for (Pack p : packs.packs) {
- p.close();
- }
+ Pack.close(Set.of(packs.packs));
}
}
@@ -484,9 +483,7 @@ class PackDirectory {
return old;
}
- for (Pack p : forReuse.values()) {
- p.close();
- }
+ Pack.close(new HashSet<>(forReuse.values()));
if (list.isEmpty()) {
return new PackList(snapshot, NO_PACKS.packs);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java
index 30f8240aa9..3ec7e6e666 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java
@@ -17,6 +17,7 @@ import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.Map;
import java.util.Random;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -397,7 +398,11 @@ public class WindowCache {
}
static final void purge(Pack pack) {
- cache.removeAll(pack);
+ purge(Collections.singleton(pack));
+ }
+
+ static final void purge(Set<Pack> packs) {
+ cache.removeAll(packs);
}
/** cleanup released and/or garbage collected windows. */
@@ -710,20 +715,21 @@ public class WindowCache {
/**
* Clear all entries related to a single file.
* <p>
- * Typically this method is invoked during {@link Pack#close()}, when we
- * know the pack is never going to be useful to us again (for example, it no
- * longer exists on disk). A concurrent reader loading an entry from this
- * same pack may cause the pack to become stuck in the cache anyway.
+ * Typically this method is invoked during {@link Pack#close()}, or
+ * {@link Pack#close(Set)}, when we know the packs are never going to be
+ * useful to us again (for example, they no longer exist on disk after gc).
+ * A concurrent reader loading an entry from these same packs may cause a
+ * pack to become stuck in the cache anyway.
*
- * @param pack
- * the file to purge all entries of.
+ * @param packs
+ * the files to purge all entries of.
*/
- private void removeAll(Pack pack) {
+ private void removeAll(Set<Pack> packs) {
for (int s = 0; s < tableSize; s++) {
final Entry e1 = table.get(s);
boolean hasDead = false;
for (Entry e = e1; e != null; e = e.next) {
- if (e.ref.getPack() == pack) {
+ if (packs.contains(e.ref.getPack())) {
e.kill();
hasDead = true;
} else if (e.dead)