]> source.dussan.org Git - jgit.git/commitdiff
Remove unnecessary note fanout when removing notes 55/1855/4
authorShawn O. Pearce <spearce@spearce.org>
Fri, 5 Nov 2010 02:01:51 +0000 (19:01 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Fri, 12 Nov 2010 22:01:28 +0000 (14:01 -0800)
Fanout level notes trees are combined back together into a flat leaf
level tree if during a removal of a subtree there are less than 3/4 of
the fanout subtrees still existing, and the size of the combined leaf
is under the 256 split limit noted above.

This rule is used because deletes are less common than insertions, and
SHA-1's relatively uniform distribution suggests that with only 192
subtrees existing in the fanout, there should be approximately 192
names in the combined replacement leaf tree.

Change-Id: Ia9d145ffd5454982509fc40906bc4dbbf2b13952
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java
org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java
org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java

index ae34938eecffbf375e1835d91662b9a02a5c730f..e1b96eaae902328142dba581d37fe877bfe8c359 100644 (file)
@@ -158,6 +158,33 @@ class FanoutBucket extends InMemoryNoteBucket {
                };
        }
 
+       @Override
+       int estimateSize(AnyObjectId noteOn, ObjectReader or) throws IOException {
+               // If most of this fan-out is full, estimate it should still be split.
+               if (LeafBucket.MAX_SIZE * 3 / 4 <= cnt)
+                       return 1 + LeafBucket.MAX_SIZE;
+
+               // Due to the uniform distribution of ObjectIds, having less nodes full
+               // indicates a good chance the total number of children below here
+               // is less than the MAX_SIZE split point. Get a more accurate count.
+
+               MutableObjectId id = new MutableObjectId();
+               id.fromObjectId(noteOn);
+
+               int sz = 0;
+               for (int cell = 0; cell < 256; cell++) {
+                       NoteBucket b = table[cell];
+                       if (b == null)
+                               continue;
+
+                       id.setByte(prefixLen >> 1, cell);
+                       sz += b.estimateSize(id, or);
+                       if (LeafBucket.MAX_SIZE < sz)
+                               break;
+               }
+               return sz;
+       }
+
        @Override
        InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData,
                        ObjectReader or) throws IOException {
@@ -182,6 +209,15 @@ class FanoutBucket extends InMemoryNoteBucket {
                                if (cnt == 0)
                                        return null;
 
+                               if (estimateSize(noteOn, or) < LeafBucket.MAX_SIZE) {
+                                       // We are small enough to just contract to a single leaf.
+                                       InMemoryNoteBucket r = new LeafBucket(prefixLen);
+                                       for (Iterator<Note> i = iterator(noteOn, or); i.hasNext();)
+                                               r = r.append(i.next());
+                                       r.nonNotes = nonNotes;
+                                       return r;
+                               }
+
                                return this;
 
                        } else if (n != b) {
@@ -268,6 +304,11 @@ class FanoutBucket extends InMemoryNoteBucket {
                        return load(objId, reader).iterator(objId, reader);
                }
 
+               @Override
+               int estimateSize(AnyObjectId objId, ObjectReader or) throws IOException {
+                       return load(objId, or).estimateSize(objId, or);
+               }
+
                @Override
                InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData,
                                ObjectReader or) throws IOException {
index 068a4c24c87e2ce52bcd42ba787479c8e210dad2..af6c6f455ea9e4674d0eb3c23f6dc9fe75548c53 100644 (file)
@@ -129,6 +129,11 @@ class LeafBucket extends InMemoryNoteBucket {
                };
        }
 
+       @Override
+       int estimateSize(AnyObjectId noteOn, ObjectReader or) throws IOException {
+               return cnt;
+       }
+
        InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData,
                        ObjectReader or) throws IOException {
                int p = search(noteOn);
index e13067cc12a0f7bfcbe46486d89776e2d6a75122..defc37dbec007daaec805aa7bcd2440e95d3f6da 100644 (file)
@@ -64,6 +64,9 @@ abstract class NoteBucket {
        abstract Iterator<Note> iterator(AnyObjectId objId, ObjectReader reader)
                        throws IOException;
 
+       abstract int estimateSize(AnyObjectId noteOn, ObjectReader or)
+                       throws IOException;
+
        abstract InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData,
                        ObjectReader reader) throws IOException;