Метод Java занимает, по-видимому, много времени, которое я не могу учесть

Используя JProfiler, я обнаружил горячую точку в своем Java-коде, которую не могу понять. JProfiler объясняет, что этот метод занимает в среднем 150 с (674 с без прогрева), не считая времени, необходимого для вызова методов-потомков. 150 секунд может показаться немного, но в этом приложении они складываются (и это испытывают мои пользователи), а также кажутся большими по сравнению с другими методами, которые кажутся мне более сложными, чем этот. Поэтому для меня это важно.

private boolean assertReadAuthorizationForFields(Object entity, Object[] state,
        String[] propertyNames) {
    boolean changed = false;
    final List<Field> fields = FieldUtil.getAppropriatePropertyFields(entity, propertyNames);
    // average of 14 fields to iterate over
    for (final Field field : fields) {
        // manager.getAuthorization returns an enum type
        // manager is a field referencing another component
        if (manager.getAuthorization(READ, field).isDenied()) {
            FieldUtil.resetField(field.getName(), state, propertyNames);
            changed = true;
        }
    }
    return changed;
}

Я для себя минимизировал этот метод в разных направлениях, но он никогда не учит меня многому полезному. Я не могу не подчеркнуть, что продолжительность, сообщаемая JProfiler (150 с), касается только кода в этом методе и не включает время, необходимое для выполнения getAuthorization, isDenied, resetField и т. д. Именно поэтому я начинаю с того, что просто публикую этот фрагмент без особого контекста, поскольку проблема, похоже, связана с этим кодом, а не с последующими вызовами методов-потомков.

Может быть, вы можете возразить, почему, если вы чувствуете, что я вижу призраков :) В любом случае, спасибо за ваше время!


person Sander Verhagen    schedule 17.03.2013    source источник
comment
Для профилирования требуется период прогрева (для JIT). Вы разогреваетесь? JIT отключен?   -  person Java42    schedule 17.03.2013
comment
Это хороший момент. Хотя я знал об этом, возможно, я ошибся. Я обновлю свой пост, и, учитывая количество времени, которое требуется после нескольких разминочных раундов, я разделился во мнениях относительно того, считаю ли я это чрезмерным... может быть, мне следует удалить вопрос... может быть нет :)   -  person Sander Verhagen    schedule 17.03.2013
comment
Используете ли вы выборку ЦП или динамическое инструментирование с JProfiler?   -  person jonathan.cone    schedule 17.03.2013
comment
Не удаляйте. Вы сами сможете ответить на свой вопрос, если разгадаете загадку.   -  person Java42    schedule 17.03.2013
comment
Я смотрю на дерево вызовов и горячие точки соответственно. Dynamic Instrumentation фактически настроен для моего сеанса.   -  person Sander Verhagen    schedule 17.03.2013
comment
Какой список возвращает FieldUtil.getAppropriatePropertyFields()? Если среднее значение равно 14, какое минимальное/максимальное число может быть возвращено? Я предполагаю, что почти все время проходит в петле.   -  person bchurchill    schedule 17.03.2013
comment
При 150 мкс потребуется более 600 вызовов, чтобы увеличить время отклика на 0,1 секунды. Возможно, вопрос, который нужно задать, заключается в том, нужно ли вам вызывать его так много раз.   -  person Jim Garrison    schedule 17.03.2013
comment
Метод getAppropriatePropertyFields возвращает List<Field>. В примере профиля я обновляю веб-страницу, на которой информация о пользователе сначала считывается из базы данных, а затем извлекается список из 594 записей данных, обе из которых включают этот метод, то есть всего 595 вызовов. Пользовательские данные могут включать немного меньше полей, 14 относятся к этим 594 записям данных.   -  person Sander Verhagen    schedule 17.03.2013
comment
Вы используете Reflection (т.е. java.lang.reflect)? Это может быть ужасно медленно! SecurityManager может привести к задержкам. Если поля представляют собой примитивы, при доступе к их значениям возникает неявная упаковка/обтекание.   -  person gb96    schedule 04.04.2013
comment
Извините, но мне пришлось отвлечь внимание от этого конкретного вопроса. Я могу или не могу вернуться к нему в будущем, но отладка стоит мне много времени, которое в настоящее время не выходит за рамки критериев усилия/результата.   -  person Sander Verhagen    schedule 27.04.2013
comment
возможный дубликат производительности отражения Java   -  person Raedwald    schedule 15.06.2013


Ответы (3)


Поведение кандидата, которое может замедлить вас:

  • Главный эффект: Очевидно, итерация. Если у вас много полей... Вы говорите, что в среднем 14, что довольно много.
  • Основной эффект: встраивание горячих точек будет означать, что вызываемые методы будут включены в ваше время, и это может быть заметно, потому что ваши вызовы методов используют отражение. getAppropriatePropertyFields анализирует метаданные определения поля класса; resetField динамически вызывает методы установки (возможно, используя Method.invoke()??). Если вы отчаянно нуждаетесь в производительности, вы можете использовать кеш через HashSet (сопоставление ElementClass->FieldMetadataAndMethodHandle). Он может содержать метаданные полей и MethodHandles методов установки (вместо использования method.invoke, который медленный). Тогда вы будете размышлять только во время запуска приложения и будете использовать быструю поддержку dynamicInvoke JVM.
  • Незначительный эффект, но умноженный на количество итераций: если у вас есть очень большие массивы для имен состояний и свойств, и они используют примитивные поля, то они будут включать некоторую степень копирования во время вызовов метода (фактически параметры метода передаются по «значению» означает передачу по ссылке / передачу по копии примитивов)
person Glen Best    schedule 21.04.2013

Я предлагаю вам рассчитать время метода самостоятельно, так как профилировщик не всегда дает точное время.

Создайте микро-тест только с этим кодом и замерьте его как минимум на 2 секунды. Чтобы выяснить, насколько сильно различаются вызовы методов, закомментируйте их и жестко закодируйте возвращаемые ими значения.

person Peter Lawrey    schedule 17.03.2013
comment
Две причины того, что профилировщики выборки сообщают время от времени неточно: 1) Если JIT решит встроить метод, этот метод никогда не будет сообщаться независимо. Вызванные методы также сообщаются независимо (даже после прогрева)? В противном случае они могут быть встроены, и в этом случае их время будет неточно привязано к assertReadAuthorizationForFields(). 2) Может пройти довольно много времени, прежде чем выборка стабилизируется и покажет стабильное время. Стабильны ли тайминги, которые вы видите в JProfiler, от одного прогона к другому? - person AaronD; 18.03.2013

Я думаю, проблема в том, что FieldUtil использует Reflection и не кэширует используемые поля.

person jontejj    schedule 31.05.2013