Skip to content

Commit 887cb08

Browse files
authored
Improve array iterator (#19)
* Improve ArrayIterator performance. For compact arrays, the old implementation was quadratic, resulting in absolutely terrible performance for large arrays. * Prefer ArrayIterator over index based access when iterating arrays. * Fix deserializeArray.
1 parent de74bb2 commit 887cb08

File tree

5 files changed

+26
-9
lines changed

5 files changed

+26
-9
lines changed

src/main/java/com/arangodb/velocypack/ArrayIterator.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,21 @@ public ArrayIterator(final VPackSlice slice) throws VPackValueTypeException {
3535
if (!slice.isArray()) {
3636
throw new VPackValueTypeException(ValueType.ARRAY);
3737
}
38+
if (size > 0) {
39+
current = slice.getNth(0).getStart();
40+
}
3841
}
3942

4043
@Override
4144
public VPackSlice next() {
42-
final VPackSlice next;
4345
if (hasNext()) {
44-
next = slice.get((int) position++);
46+
final VPackSlice next = getCurrent();
47+
position++;
48+
current += next.getByteSize();
49+
return next;
4550
} else {
4651
throw new NoSuchElementException();
4752
}
48-
return next;
4953
}
5054

5155
@Override

src/main/java/com/arangodb/velocypack/VPack.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -667,8 +667,9 @@ private <T> Object deserializeArray(final VPackSlice parent, final VPackSlice vp
667667
final int length = vpack.getLength();
668668
final Class<?> componentType = ((Class<?>) type).getComponentType();
669669
final Object value = Array.newInstance(componentType, length);
670-
for (int i = 0; i < length; i++) {
671-
Array.set(value, i, getValue(parent, vpack.get(i), componentType, null));
670+
int i = 0;
671+
for (final Iterator<VPackSlice> iterator = vpack.arrayIterator(); iterator.hasNext(); ) {
672+
Array.set(value, i++, getValue(parent, iterator.next(), componentType, null));
672673
}
673674
return value;
674675
}

src/main/java/com/arangodb/velocypack/VPackParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ private void parseArray(final VPackSlice value, final StringBuilder json, final
324324
throws VPackException {
325325
json.append(ARRAY_OPEN);
326326
int added = 0;
327-
for (int i = 0; i < value.getLength(); i++) {
328-
final VPackSlice valueAt = value.get(i);
327+
for (final Iterator<VPackSlice> iterator = value.arrayIterator(); iterator.hasNext();) {
328+
final VPackSlice valueAt = iterator.next();
329329
if (!valueAt.isNull() || includeNullValues) {
330330
if (added++ > 0) {
331331
json.append(SEPARATOR);

src/main/java/com/arangodb/velocypack/VPackSlice.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ private VPackSlice getNthKey(final int index) {
783783
return new VPackSlice(vpack, start + getNthOffset(index));
784784
}
785785

786-
private VPackSlice getNth(final int index) {
786+
public VPackSlice getNth(final int index) {
787787
return new VPackSlice(vpack, start + getNthOffset(index));
788788
}
789789

src/test/java/com/arangodb/velocypack/VPackSliceTest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ private void checkArray(final long[] expected, final byte[] vpack) throws VPackE
873873
}
874874

875875
@Test
876-
public void arrayIterator() throws VPackException {
876+
public void arrayIteratorOnCompactArray() throws VPackException {
877877
final Collection<String> expected = Arrays.asList("a", "b", "c", "d", "e", "f");
878878
final VPackSlice slice = new VPackSlice(new byte[] { 0x13, 0x0f, 0x41, 0x61, 0x41, 0x62, 0x41, 0x63, 0x41, 0x64,
879879
0x41, 0x65, 0x41, 0x66, 0x06 });
@@ -885,6 +885,18 @@ public void arrayIterator() throws VPackException {
885885
}
886886
}
887887

888+
@Test
889+
public void arrayIteratorOnArrayWithIndexTable() throws VPackException {
890+
final Collection<Integer> expected = Arrays.asList(1, 42, 3);
891+
final VPackSlice slice = new VPackSlice(new byte[] { 0x06, 0x0a, 0x03, 0x31, 0x20, 0x2a, 0x33, 0x03, 0x04, 0x06 });
892+
final Iterator<VPackSlice> iteratorSlice = slice.arrayIterator();
893+
for (final Integer i : expected) {
894+
final VPackSlice next = iteratorSlice.next();
895+
assertThat(next.isInteger(), is(true));
896+
assertThat(next.getAsInt(), is(i));
897+
}
898+
}
899+
888900
@Test
889901
public void objectIterator() throws VPackException {
890902
// {"a":"test","b":"test","c":"test"}

0 commit comments

Comments
 (0)