From 62fe7c7313e4e7a4339fe9df3a9dc2335461df29 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 18 Mar 2011 09:07:25 -0700 Subject: [PATCH] BlockList: Micro-optimize appending from another BlockList Simple variant of addAll() that knows how to copy large segments quickly using System.arraycopy() rather than looping through with an Iterator object. Change-Id: Icb50a8f87fe9180ea28b6920f473bb9e70c300f1 Signed-off-by: Shawn O. Pearce --- .../org/eclipse/jgit/util/BlockListTest.java | 18 ++++++++ .../src/org/eclipse/jgit/util/BlockList.java | 46 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java index 7151af156..8b042bd67 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java @@ -281,6 +281,24 @@ public class BlockListTest { assertEquals(Integer.valueOf(1), list.get(list.size() - 1)); } + @Test + public void testAddAllFromOtherList() { + BlockList src = new BlockList(4); + int cnt = BlockList.BLOCK_SIZE * 2; + + for (int i = 0; i < cnt; i++) + src.add(Integer.valueOf(42 + i)); + src.add(Integer.valueOf(1)); + + BlockList dst = new BlockList(4); + dst.add(Integer.valueOf(255)); + dst.addAll(src); + assertEquals(cnt + 2, dst.size()); + for (int i = 0; i < cnt; i++) + assertEquals(Integer.valueOf(42 + i), dst.get(i + 1)); + assertEquals(Integer.valueOf(1), dst.get(dst.size() - 1)); + } + @Test public void testFastIterator() { BlockList list = new BlockList(4); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java index ac29771d8..50715acb2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java @@ -141,6 +141,52 @@ public class BlockList extends AbstractList { return old; } + /** + * Quickly append all elements of another BlockList. + * + * @param src + * the list to copy elements from. + */ + public void addAll(BlockList src) { + if (src.size == 0) + return; + + int srcDirIdx = 0; + for (; srcDirIdx < src.tailDirIdx; srcDirIdx++) + addAll(src.directory[srcDirIdx], 0, BLOCK_SIZE); + if (src.tailBlkIdx != 0) + addAll(src.tailBlock, 0, src.tailBlkIdx); + } + + /** + * Quickly append all elements from an array. + * + * @param src + * the source array. + * @param srcIdx + * first index to copy. + * @param srcCnt + * number of elements to copy. + */ + public void addAll(T[] src, int srcIdx, int srcCnt) { + while (0 < srcCnt) { + int i = tailBlkIdx; + int n = Math.min(srcCnt, BLOCK_SIZE - i); + if (n == 0) { + // Our tail is full, expand by one. + add(src[srcIdx++]); + srcCnt--; + continue; + } + + System.arraycopy(src, srcIdx, tailBlock, i, n); + tailBlkIdx += n; + size += n; + srcIdx += n; + srcCnt -= n; + } + } + @Override public boolean add(T element) { int i = tailBlkIdx;