Improve Hashmap Object iteration speed.
The iteration speed up is improved around %15-20 percent for Chrome.
As hasNext calls duplicated on iteration (one direct call
and another call through checkState(hasNext)), improves
the iterator implementation to cache the hasNext value.
The patch also removes the extra checks on internal HashMap
iterator implementation as they are only used internally and
from a single place that doesn't require the extra checking.
Note that, HashMap iterators also were not well optimized even
with the configurable Preconditions because hasNext method had
side effects.
Change-Id: I7617fa7a605d7a0cf204338a55201af6a30ac18d
Review-Link: https://gwt-review.googlesource.com/#/c/13490/
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java b/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
index 1d27463..1d96828 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
@@ -79,6 +79,7 @@
private Iterator<Entry<K, V>> stringMapEntries = stringMap.iterator();
private Iterator<Entry<K, V>> current = stringMapEntries;
private Iterator<Entry<K, V>> last;
+ private boolean hasNext = computeHasNext();
public EntrySetIterator() {
recordLastKnownStructure(AbstractHashMap.this, this);
@@ -86,6 +87,10 @@
@Override
public boolean hasNext() {
+ return hasNext;
+ }
+
+ private boolean computeHasNext() {
if (current.hasNext()) {
return true;
}
@@ -102,7 +107,10 @@
checkElement(hasNext());
last = current;
- return current.next();
+ Entry<K, V> rv = current.next();
+ hasNext = computeHasNext();
+
+ return rv;
}
@Override
@@ -112,6 +120,8 @@
last.remove();
last = null;
+ hasNext = computeHasNext();
+
recordLastKnownStructure(AbstractHashMap.this, this);
}
}
diff --git a/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java b/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java
index 1d78932..1422114 100644
--- a/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java
+++ b/user/super/com/google/gwt/emul/java/util/InternalHashCodeMap.java
@@ -17,9 +17,6 @@
import static java.util.ConcurrentModificationDetector.structureChanged;
-import static javaemul.internal.InternalPreconditions.checkElement;
-import static javaemul.internal.InternalPreconditions.checkState;
-
import java.util.AbstractMap.SimpleEntry;
import java.util.InternalJsMapFactory.InternalJsIterator;
import java.util.InternalJsMapFactory.InternalJsIteratorEntry;
@@ -132,22 +129,17 @@
@Override
public Entry<K, V> next() {
- checkElement(hasNext());
-
lastEntry = chain[itemIndex++];
return lastEntry;
}
@Override
public void remove() {
- checkState(lastEntry != null);
-
InternalHashCodeMap.this.remove(lastEntry.getKey());
// Unless we are in a new chain, all items have shifted so our itemIndex should as well...
if (itemIndex != 0) {
itemIndex--;
}
- lastEntry = null;
}
};
}
diff --git a/user/super/com/google/gwt/emul/java/util/InternalStringMap.java b/user/super/com/google/gwt/emul/java/util/InternalStringMap.java
index 443d225..a81253e 100644
--- a/user/super/com/google/gwt/emul/java/util/InternalStringMap.java
+++ b/user/super/com/google/gwt/emul/java/util/InternalStringMap.java
@@ -17,9 +17,6 @@
import static java.util.ConcurrentModificationDetector.structureChanged;
-import static javaemul.internal.InternalPreconditions.checkElement;
-import static javaemul.internal.InternalPreconditions.checkState;
-
import java.util.InternalJsMapFactory.InternalJsIterator;
import java.util.InternalJsMapFactory.InternalJsIteratorEntry;
import java.util.InternalJsMapFactory.InternalJsMap;
@@ -99,18 +96,13 @@
}
@Override
public Entry<K, V> next() {
- checkElement(hasNext());
-
last = current;
current = entries.next();
return newMapEntry(last, valueMod);
}
@Override
public void remove() {
- checkState(last != null);
-
InternalStringMap.this.remove(last.getKey());
- last = null;
}
};
}