Приводит ли создание объекта с использованием отражения вместо вызова конструктора класса какие-либо существенные различия в производительности?
java
performance
optimization
reflection
dmanxiii
источник
источник
Ответы:
Да, конечно. Поиск класса с помощью отражения по величине , дороже.
Цитирую документацию Java по рефлексии :
Вот простой тест, который я взломал за 5 минут на моей машине под управлением Sun JRE 6u10:
С этими результатами:
Имейте в виду, что поиск и создание экземпляров выполняются вместе, а в некоторых случаях поиск может быть подвергнут рефакторингу, но это только базовый пример.
Даже если вы просто создадите экземпляр, вы все равно получите удар по производительности:
Опять YMMV.
источник
Да, это медленнее.
Но помните чертово правило № 1 - ОПТИМИЗАЦИЯ ПРЕДВАРИТЕЛЬНОЙ СИЛЫ - КОРЕНЬ ВСЕГО ЗЛА
(Ну, может быть связано с № 1 для СУХОГО)
Клянусь, если бы кто-нибудь подошел ко мне на работе и спросил меня об этом, я бы очень внимательно следил за их кодом в течение следующих нескольких месяцев.
Вы никогда не должны оптимизировать, пока не будете уверены, что вам это нужно, до тех пор просто пишите хороший, читаемый код.
О, и я не имею в виду писать глупый код тоже. Просто подумайте о том, как сделать это самым чистым способом - без копирования и вставки и т.д. Плохое программирование)
Меня пугает, когда я слышу подобные вопросы, но потом я забываю, что все должны пройти изучение всех правил самостоятельно, прежде чем они действительно получат это. Вы получите это после того, как потратили человек-месяц на отладку чего-то, что кто-то «оптимизировал».
РЕДАКТИРОВАТЬ:
Интересная вещь произошла в этой теме. Посмотрите ответ № 1, это пример того, насколько мощным компилятор является в оптимизации вещей. Тест полностью недействителен, потому что неотражающий экземпляр может быть полностью исключен.
Урок? Никогда не оптимизируйте, пока вы не написали чистое, аккуратно закодированное решение и не доказали, что оно слишком медленное.
источник
Вы можете обнаружить, что A a = new A () оптимизируется JVM. Если вы помещаете объекты в массив, они не так хорошо работают. ;) Следующие принты ...
Это говорит о том, что на моей машине разница составляет около 150 нс.
источник
Class.getDeclaredMethod
), а затем позвонюMethod.invoke
несколько раз? Я использую отражение один раз или столько раз, сколько я его вызываю? Последующий вопрос, а что если вместоMethod
него этоConstructor
сделатьConstructor.newInstance
несколько раз?Если действительно нужно что-то быстрее, чем отражение, и это не просто преждевременная оптимизация, то генерация байт-кода с помощью ASM вариант или библиотеки более высокого уровня - вариант. Генерация байт-кода в первый раз медленнее, чем просто использование отражения, но как только байт-код сгенерирован, он работает так же быстро, как обычный код Java, и будет оптимизирован компилятором JIT.
Некоторые примеры приложений, которые используют генерацию кода:
Вызов методов на прокси, сгенерированных CGLIB , немного быстрее, чем динамические прокси Java , потому что CGLIB генерирует байт-код для своих прокси, но динамические прокси используют только отражение ( я измерил CGLIB примерно в 10 раз быстрее при вызовах методов, но создание прокси было медленнее).
JSerial генерирует байт-код для чтения / записи полей сериализованных объектов вместо использования отражения. На сайте JSerial есть несколько тестов .
Я не уверен на 100% (и сейчас мне не хочется читать исходники), но я думаю, что Guice генерирует байт-код для внедрения зависимостей. Поправьте меня если я ошибаюсь.
источник
«Значительный» полностью зависит от контекста.
Если вы используете рефлексию для создания одного объекта-обработчика на основе какого-либо файла конфигурации, а затем тратите оставшееся время на выполнение запросов к базе данных, то это не имеет значения. Если вы создаете большое количество объектов с помощью отражения в узком цикле, то да, это важно.
В общем, гибкость дизайна (где это необходимо!) Должна стимулировать использование отражения, а не производительности. Однако, чтобы определить, является ли производительность проблемой, вам нужно профилировать, а не получать произвольные ответы от дискуссионного форума.
источник
С отражением есть некоторые издержки, но на современных виртуальных машинах они намного меньше, чем раньше.
Если вы используете отражение для создания каждого простого объекта в вашей программе, значит что-то не так. Использование его изредка, когда у вас есть веская причина, не должно быть проблемой вообще.
источник
Да, при использовании Reflection наблюдается снижение производительности, но возможный обходной путь оптимизации - кэширование метода:
приведет к:
[java] вызов метода 1000000 раз рефлексивно с поиском занял 5618 миллис
[java] вызов метода 1000000 раз рефлексивно с кешем занял 270 миллис
источник
Отражение медленное, хотя распределение объектов не так безнадежно, как другие аспекты отражения. Достижение эквивалентной производительности с помощью основанной на отражении реализации требует от вас написания кода, чтобы jit мог определить, какой класс создается. Если идентичность класса не может быть определена, тогда код распределения не может быть встроен. Хуже того, escape-анализ завершается неудачно, и объект не может быть размещен в стеке. Если вам повезет, профилирование во время выполнения JVM может прийти на помощь, если этот код перегреется, и может динамически определить, какой класс преобладает, и может оптимизировать его.
Помните, что микробенчмарки в этой теме глубоко испорчены, поэтому возьмите их с небольшим количеством соли. Наименьший недостаток на сегодняшний день - у Питера Лоури: он выполняет прогрев прогона, чтобы соединить методы, и он (сознательно) побеждает анализ побега, чтобы убедиться, что распределение действительно происходит. Но даже у этого есть свои проблемы: например, можно ожидать, что огромное количество хранилищ массивов побеждает кеши и буферы хранилищ, так что в конечном итоге это будет в основном ориентиром для памяти, если ваши выделения очень быстрые. (Благодарность Питеру за то, что он сделал правильное заключение: разница составляет «150 нс», а не «2,5х». Я подозреваю, что он зарабатывает этим на жизнь.)
источник
Интересно, что установка setAccessible (true), которая пропускает проверки безопасности, снижает стоимость на 20%.
Без setAccessible (true)
С setAccessible (true)
источник
1000000
вызовов?setAccessible()
может иметь гораздо больше различий в целом, особенно для методов с несколькими аргументами, поэтому он всегда должен вызываться.Да, это значительно медленнее. Мы выполняли некоторый код, который сделал это, и хотя у меня пока нет доступных метрик, конечным результатом было то, что нам пришлось реорганизовать этот код, чтобы не использовать отражение. Если вы знаете, что это за класс, просто вызовите конструктор напрямую.
источник
В doReflection () это накладные расходы из-за Class.forName («misc.A») (что потребует поиска класса, потенциально сканирующего путь к классу в файловой системе), а не newInstance (), вызываемого в классе. Мне интересно, как будет выглядеть статистика, если Class.forName ("misc.A") выполняется только один раз вне цикла for, это не обязательно должно выполняться для каждого вызова цикла.
источник
Да, всегда будет медленнее создавать объект путем отражения, потому что JVM не может оптимизировать код во время компиляции. См. Учебники Sun / Java Reflection для получения более подробной информации.
Смотрите этот простой тест:
источник
Class.forName()
) от экземпляра (newInstance ()), потому что они значительно различаются по своим характеристикам производительности, и вы можете иногда избегать повторного поиска в хорошо спроектированной системе.Часто вы можете использовать Apache Commons BeanUtils или PropertyUtils, которые самоанализ (в основном они кэшируют метаданные о классах, поэтому им не всегда нужно использовать отражение).
источник
Я думаю, это зависит от того, насколько легким / тяжелым является целевой метод. если целевой метод очень легкий (например, метод получения / установки), он может быть в 1-3 раза медленнее. если целевой метод занимает около 1 миллисекунды или выше, производительность будет очень близка. Вот тест, который я сделал с Java 8 и refleasm :
Полный тестовый код доступен на GitHub: ReflectionTest.java
источник