Производительность нового оператора по сравнению с newInstance () в Java - PullRequest
10 голосов
/ 21 июля 2010

Я использовал newInstance() в своего рода критически важной области моего кода.Сигнатура метода:

<T extends SomethingElse> T create(Class<T> clasz)

Я передаю Something.class в качестве аргумента, получаю экземпляр SomethingElse, созданный с помощью newInstance().

СегодняЯ вернулся, чтобы убрать этот TODO производительности из списка, поэтому я провел несколько тестов оператора new против newInstance().Я был очень удивлен штрафом за производительность newInstance().

Я немного об этом написал, здесь: http://biasedbit.com/new-vs-newinstance/

(Извините за саморекламу ... Я бы поставилтекст здесь, но этот вопрос вырастет из пропорций.)

Я хотел бы знать, почему флаг -server обеспечивает такое повышение производительности, когда число создаваемых объектов значительно увеличивается ине для «низких» значений, скажем, 100 или 1000.

Я действительно усвоил урок со всем отражением, это просто любопытство по поводу оптимизаций, которые JVM выполняет во время выполнения, особенно с флагом -server,Также, если я делаю что-то не так в тесте, буду признателен за ваш отзыв!


Редактировать: я добавил фазу прогрева, и результаты теперь более стабильны.Спасибо за ввод!

Ответы [ 3 ]

5 голосов
/ 21 июля 2010

Я усвоил урок со всей рефлексией, это просто любопытство по поводу оптимизаций, которые JVM выполняет во время выполнения, особенно с флагом -server.Кроме того, если я делаю что-то не так в тесте, буду признателен за ваш отзыв!

Отвечая сначала на вторую часть, ваш код, кажется, делает классическую ошибку для микропроцессоров Java ине «прогревать» JVM перед выполнением измерений.Ваше приложение должно запустить метод, который выполняет тест несколько раз, игнорируя первые несколько итераций ... по крайней мере до тех пор, пока числа не стабилизируются.Причина этого заключается в том, что JVM приходится много работать для запуска приложения;например, загрузка классов и (когда они запускались несколько раз) JIT-компиляция методов, на которые тратится значительное время приложения.

Я думаю, что причина в том, что "-server" имеет значение, заключается в том, что (среди другихвещи) это изменяет правила, которые определяют, когда JIT компилируется.Предполагается, что для «сервера» лучше JIT раньше, это дает более медленный запуск, но лучшую производительность.(Напротив, «клиент» настроен так, чтобы отложить JIT-компиляцию, чтобы пользователь быстрее получил рабочий GUI.)

1 голос
/ 21 июля 2010

ИМХО снижение производительности происходит от механизма загрузки классов.В случае отражения используются все механизмы защиты и, следовательно, штраф за создание выше.В случае нового оператора классы уже загружены в ВМ (проверено и подготовлено загрузчиком классов по умолчанию), и фактическая реализация является дешевым процессом.Параметр -server выполняет много JIT-оптимизаций для часто используемого кода.Вы можете попробовать это также с параметром -batch, который компенсирует время запуска, но затем код будет работать быстрее.

1 голос
/ 21 июля 2010

Кроме всего прочего, профиль сбора мусора для опции -server имеет существенно отличающиеся размеры места для выживших значения по умолчанию.

При ближайшем рассмотрении я вижу, что ваш пример - микро-эталон и результаты могут быть нелогичными.Например, на моей платформе повторные вызовы newInstance() эффективно оптимизируются при повторных запусках, благодаря чему newInstance() отображается в 12,5 раз быстрее, чем new.

...