GWT: Как избежать обращений к dynamicCast и canCastUnsafe в сгенерированном коде JavaScript? - PullRequest
7 голосов
/ 27 марта 2009

Я пишу некоторые структуры данных специального назначения на Java, предназначенные для использования в браузере (скомпилированы в JavaScript с GWT).

Я пытаюсь сопоставить производительность некоторых встроенных классов JDK. Я замечаю, что все работает достаточно быстро, но когда я сравниваю свою трассировку кода с некоторым из эмулируемого кода JDK, у меня появляется множество обращений к dynamicCast и canCastUnsafe, в то время как классы эмуляции JDK этого не делают. И это также объясняет разницу в производительности ...

Кто-нибудь из гуру GWT знает, как этого избежать? Это накладные расходы на 20%: - (

подробности:

Вот вывод профиля (захваченный в Firebug) для 10000 вставок случайных целых чисел, от 0 до 100000, в две разные структуры данных:

Реализация Google TreeMap для java.util.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

Дополнительные наблюдения:

  • Та же проблема для другой структуры данных, которую я создал (SkipList).
  • dynamicCast применяется в функции сравнения:

    cmp = dynamicCast (right.key, 4) .compareTo $ (ключ);

  • dynamicCast исчезает, если класс не реализует Map (т. Е. Просто удаляет «реализует Map» из класса. Не имеет значения, доступен ли он через интерфейс или напрямую. Это приводит к тому, что строка компилируется в :

    cmp = right.key.compareTo $ (ключ);

Это соответствующий раздел исходного кода Java из 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);

            ...
        }
    }
}

Ответы [ 5 ]

4 голосов
/ 01 апреля 2009

К сожалению, я до сих пор не совсем понимаю причину, но из моего опыта это видно из явных приведений, таких как:

((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); 
}-*/;
1 голос
/ 27 июня 2011

Обновленный ответ для GWT версии 2.1 и выше:

Начиная с GWT 2.1 (по крайней мере, это первое упоминание), компилятор GWT имеет новый аргумент компилятора под названием -XdisableCastChecking, который отключает все проверки приведения во время выполнения. Обратите внимание, что эта опция помечена как экспериментальная (возможно, потому, что это сильно затруднит отладку исключений приведения классов).

В моем приложении dynamicCast вызывалось тысячи раз за короткий прогон профиля, и это был 3-й самый трудоемкий метод в профилировщике Firebug. Использование этого аргумента компилятора значительно уменьшило количество сообщений «Long Duration Events» в Chrome Speed ​​Tracer.

См. Опции компилятора GWT для этого и других аргументов компилятора.

1 голос
/ 01 апреля 2009

Не знаю, видели ли вы эту тему на форуме автора GWT ...

По сути, он начинается с той же проблемы, которую вы определили, предлагает несколько новых флагов компилятора и продолжает показывать, как использовать JSNI для обхода приведений.

Редактировать В стволе GWT есть новый флаг компилятора. См вики ...

0 голосов
/ 15 ноября 2013

Это определенно проблема компилятора: у меня проблема в следующей строке:

final DefaultIconedSuggestBox<SuggestValueProxy, IconedValueHolderItem<SuggestValueProxy>> fieldValueWidget = getCategoryWidget().getFieldValueWidget();

Я действительно не знаю, как я могу обойти это: эта строка происходит в момент, когда я меняю модуль на другой (возможно, это связано с проблемой разделителя кода: даже если я не использую разделение кода) : Я просто загружаю другую страницу другим модулем)

0 голосов
/ 31 марта 2009

Может ли использование дженериков и символов подстановки Java 1.5 избежать этого?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...