问题描述
我正在用Java编写一些特殊用途的数据结构,用于浏览器(使用GWT编译成JavaScript)。
我试图匹配某些内置JDK类的性能我注意到事情运行速度相当快,但是当我将代码跟踪与某些模拟的JDK代码进行比较时,我的模拟JDK模拟了很多对dynamicCast和canCastUnsafe的调用类没有。它只是考虑到了性能上的差异......
任何GWT专家都知道如何避免这种情况?这是相当于20%的开销: - ($ / b
$ b
详细信息:
以下是配置文件输出(在Firebug中捕获)为10000个插入的随机整数,在0到100,000之间分成两个不同的数据结构:
Google的java.util.TreeMap的TreeMap实现(红黑树):
$ b $ pre $ 配置文件(4058.602ms,687545调用)
函数调用百分比自己的时间
$ 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树):
配置文件(5397.686ms,898603调用)
函数调用百分比自己的时间
$ 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
其他观察:
- 我为另一个数据结构(SkipList)创建了同样的问题。
-
dynamicCast正在应用于比较函数中:
cmp = dynamicCast(right.key,4).compareTo $(key);
-
如果类没有实现Map(即:只需从班级中删除实现地图。如果通过界面或直接访问,无关紧要。这会导致相同的行编译为:
cmp = right.key.compareTo $(key);
ul>
这是SkipList的Java源代码的相关部分:
private int比较(节点a,对象o){
if(比较器!=空)
返回comparator.compare((K)a.key,(K)o); $(比较< K> a.key).compareTo((K)o);
return
}
public V get(Object k){
K key =(K)k;
节点< K,V>当前=头;
for(int i = head.height-1; i> = 0; i--){
节点< K,V>对; ((right = current.right [i])!= null){
int cmp = compare(right,key);
while
...
}
}
}
$ b $ b
((Comparable)obj).compareTo(other)
生成的Javascript看起来像:
dynamicCast(obj,1).compareTo(other);
其中1是代表演员目标的生成typeId。 dynamicCast反过来调用canCastUnsafe,如果为false,则抛出ClassCastException。此值已辩论,因为这已经被托管模式捕获。
它可以用JSNI回避:
public static native int compare(Object a,Object b)/ * - {
return a。@ java.lang.Comparable :: compareTo(Ljava / lang / Object;) (b);
} - * /;
I'm writing some special purpose data structures in Java, intended for use in the browser, (compiled to JavaScript with GWT).
I'm trying to match the performance of some of the built-in JDK classes I'm noticing things run reasonably fast, but when I compare my code trace to some of the emulated JDK code, mine has lots of calls to dynamicCast and canCastUnsafe, while the JDK emulated classes do not. And it just about accounts for the difference in performance too...
Any GWT gurus out there know how to avoid this? It's amounting to a 20% overhead :-(
Details:
Here's the profile output (captured in Firebug) for 10,000 insertions of random integers, between 0 and 100,000 into two different data structures:
Google's TreeMap implementation for java.util.TreeMap (a red-black tree):
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
My Code (An AVL tree):
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
Additional observations:
- Same problem for another data structure I made (SkipList).
dynamicCast is being applied in the compare function:
cmp = dynamicCast(right.key, 4).compareTo$(key);
dynamicCast goes away if the class does not implement Map (ie: just removing " implements Map" from the class. Doesn't matter if it's accessed through the interface or directly. This results in the same line compiling to:
cmp = right.key.compareTo$(key);
This is the relevant section of Java source from SkipList:
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);
...
}
}
}
Unfortunately I'm still not exactly clear on the cause, but from my experience, it seems from explicit casts, like:
((Comparable) obj).compareTo(other)
The Javascript generated looks like:
dynamicCast(obj, 1).compareTo(other);
Where 1 is a generated typeId representing the target of the cast. dynamicCast in turn calls canCastUnsafe and if false, it throws a ClassCastException. The value of this has been debated, since this would already be caught in hosted mode.
It can be sidestepped with JSNI:
public static native int compare(Object a, Object b) /*-{
return [email protected]::compareTo(Ljava/lang/Object;)(b);
}-*/;
这篇关于GWT:如何避免在生成的JavaScript代码中调用dynamicCast和canCastUnsafe?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!