Как стать автором
Обновить

Комментарии 22

Есть еще один способ, не волшебный, правда, и не всегда применимый, но мега-крутой - compile-time кодогенерация и post-compile weaving. Последний вообще позволяет получить перфоманс "как будто бы сам написал".

Спасибо за статью. Почему Вы не используете фреймворк для микробенчмаркинга (например, jmh)? Кроме того в 18ой джаве core reflections переписали на var handles.
https://openjdk.java.net/jeps/416

Про var handles не знал, спасибо. Что насчет jmh, в данном случае его использование показалось излишним, все измерения сводились к вызову нескольких методов, да и точности используемого подхода вполне хватает.

Дело не в точности, а в достоверности и воспроизводимости. System.nanoTime с кодом в цикле может показать что угодно, т.к. не учитывается оптимизации, jit, code-кеши и прочее. JMH же создан так, чтобы абстрагироваться от всего такого и дать прикладному разработчику инструмент для написания достоверных (хотя бы для его железа) бенчмарков. Так что рекомендую в будущем использовать его.

Так они же не в цикле, а до-после... Ну да, могут врать, но не порядки же

Могут быть порядки. Основной смысл использования какого-то стандартного инструментария для бенчмаркинга - это возможность замерить нужный участок кода на разогретой JVM. Посмотрите JEP, который я скидывал выше, там замеры сделаны именно с помощью JMH.

А кеширование как вариант почему не рассматривается?

Каким образом кэширование поможет ускорить рефлективные вызовы метода? Имхо, максимум можно кэшировать получение объекта java.lang.reflect.Method, но это даст выигрыш лишь в скорости подготовки вызова.

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

P. S. Если имеется ввиду кэширование получаемой из метода информации, дабы предотвратить излишние вызовы, то это материал для совершенно другой статьи.

А можете еще чуть подробнее пояснить свою мысль? Вы же показываете код на C++, то есть, так или иначе, это не байткод.

Ну смотрите. Байт-код можно либо интепретировать, либо компилировать в платформенный код. В обоих случаях мы можем вместо какого-то метода JVM вызвать просто какую-нибудь функцию самой JVM, чем и являются интринсики.

Ну а JNI - это сложнейший комбайн, который поддерживает потокобезопасность, открывает во внешний мир API JVM и делает еще кучу вещей, необходимых для стабильного FFI.

Я правильно понял, что этот код на C++, не компилируется в .so или .dll, и не вызывается через JNI, а является частью хотспот компилятора?

Да. Если бы для каждого вызова интринсика приходилось уходить в safe point, то это было бы больно.

Ага, спасибо.

Рефлексия в Джаве помимо пользы может нести в себе кучу багов, которые потом хрен поймаешь. А так же это - отличный инструмент в руках хакера/злоумышленника. Получить доступ можно к чему угодно.

отличный инструмент в руках хакера/злоумышленника. Получить доступ можно к чему угодно.

Не могли бы развернуть вашу мысль? В текущем изложении не очень понятно в чем вы видите угрозу безопасности

Занимательные замеры времени. Вывод же несколько ограниченный. Вся разница получается за счёт компиляции метода add в одну asm инструкцию вместо нескольких десятков для reflection-а. Ну а промежуточные значения есть лишь показатель способности методом тыка подсказать компилятору, как же правильно компилировать.

Ну и про "тяжесть" рефлексии. Просто не надо писать критический код с её использованием. И в подавляющем большинстве случаев для этого нет никакой необходимости. А некритический код, исполняемый за 1 микросекунду или за 10 наносекунд - абсолютно ни на что не влияет.

Странно, что нет теста с Unsafe... Если вы уже решили прыгнуть в гигантский цикл(то есть массовые операции) то очевидно, что дальше только хардкор... И это не про суррогатный тест с рефлекшан

Как будто в этой строке не хватает использования i

lambda.call(arguments);

Для наглядной демонстрации влияния создания массива на скорость вызова был создан вне цикла "константный" массив, содержащий 5 в качестве аргумента.

А почему вы считаете, что измерили именно вызов метода 'add'? Он может заинлайнится, цикл может быть оптимизирован, а, учитывая, что поле 'value' не читается, не удивлюсь, если окажется, что и вызов метода вместе с циклом были просто удалены

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории