我正在用 Java 编写一些用于浏览器的特殊用途数据结构(使用 GWT 编译为 JavaScript)。
我正在尝试匹配一些内置 JDK 类的性能我注意到运行速度相当快,但是当我将我的代码跟踪与一些模拟的 JDK 代码进行比较时,我有很多对 dynamicCast 和 canCastUnsafe 的调用,而 JDK 模拟的类没有。它也只是解释了性能的差异......
那里有任何 GWT 大师知道如何避免这种情况吗?这相当于 20% 的开销:-(
细节:
这是将 0 到 100,000 之间的 10,000 次随机整数插入两种不同数据结构的配置文件输出(在 Firebug 中捕获):
谷歌的 java.util.TreeMap 的 TreeMap 实现(红黑树):
Profile (4058.602ms, 687545 calls)
Function Calls Percent Own Time
$insert_1 129809 41.87% 1699.367ms
$compare_0 120290 16% 649.209ms
$isRed 231166 13.33% 540.838ms
compareTo_0 120290 8.96% 363.531ms
$put_2 10000 6.02% 244.493ms
wrapArray 10000 3.46% 140.478ms
createFromSeed 10000 2.91% 118.038ms
$TreeMap$Node 10000 2.38% 96.706ms
initDim 10000 1.92% 77.735ms
initValues 10000 1.49% 60.319ms
$rotateSingle 5990 0.73% 29.55ms
TreeMap$Node 10000 0.47% 18.92ms
我的代码(AVL 树):
Profile (5397.686ms, 898603 calls)
Function Calls Percent Own Time
$insert 120899 25.06% 1352.827ms
$compare 120899 17.94% 968.17ms
dynamicCast 120899 14.12% 762.307ms <--------
$balanceTree 120418 13.64% 736.096ms
$setHeight 126764 8.93% 482.018ms
compareTo_0 120899 7.76% 418.716ms
canCastUnsafe 120899 6.99% 377.518ms <--------
$put 10000 2.59% 139.936ms
$AVLTreeMap$Node 9519 1.04% 56.403ms
$moveLeft 2367 0.36% 19.602ms
AVLTreeMap$State 9999 0.36% 19.429ms
$moveRight 2378 0.34% 18.295ms
AVLTreeMap$Node 9519 0.34% 18.252ms
$swingRight 1605 0.26% 14.261ms
$swingLeft 1539 0.26% 13.856ms
其他意见:
cmp = dynamicCast(right.key, 4).compareTo$(key);
cmp = right.key.compareTo$(key);
这是 SkipList 中 Java 源代码的相关部分:
private int compare(Node a, Object o) {
if (comparator != null)
return comparator.compare((K) a.key, (K) o);
return ((Comparable<K>) a.key).compareTo((K) o);
}
public V get(Object k) {
K key = (K) k;
Node<K, V> current = head;
for (int i = head.height - 1; i >= 0; i--) {
Node<K, V> right;
while ((right = current.right[i]) != null) {
int cmp = compare(right, key);
...
}
}
}
请您参考如下方法:
不幸的是,我仍然不清楚原因,但根据我的经验,它似乎来自明确的 Actor ,例如:
((Comparable) obj).compareTo(other)
生成的 Javascript 如下所示:
dynamicCast(obj, 1).compareTo(other);
其中 1 是生成的 typeId,表示类型转换的目标。 dynamicCast 依次调用 canCastUnsafe,如果为 false,则抛出 ClassCastException。这个值是 debated ,因为这已经在托管模式下被捕获。
可以使用 JSNI 避开它:
public static native int compare(Object a, Object b) /*-{
return a.@java.lang.Comparable::compareTo(Ljava/lang/Object;)(b);
}-*/;