Pull to refresh

Comments 7

Здравствуйте! Для android ndk тоже нужно выполнять консольные команды? Есть ли отличаи от jni в командах?

Здравствуйте! Нет, выполнять консольные команды из Android Studio не нужно, все работает из коробки. Т.е. в AS все намного проще. Советую прочитать эту статью которая рассказывает именно про AS.

Я взял ваш код на C++ и Java и сравнил без JNI, просто две разных программы. На обеих версиях, что линейной, что квадратичной, результаты идентичны для обоих языков. Разницей в 4 раза даже не пахнет.

Debian 11, AMD Ryzen Threadripper 3970X

openjdk 11.0.13 2021-10-19 запускал через java main.java.

gcc version 10.2.1 g++ -O2 -o cmp_java java.cc && ./cmp_java

В обоих случаях около 1.8 секунды при размере задачи 50_000

И это вполне ожидаемые разультаты для числодробилки, потому что на подобном коде jit особо не уступает aot.

Но возьмите задачу, которая требует больше разнородных действий, сильнее нагружает GC, использует системные api и увидите, что всё уже совсем не в пользу Java. Поэтому заявления, что java быстрее jni мягко говоря необоснованы.

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

Большое спасибо за комментарий!

Вы действительно правы! Использование native сейчас, кажется оправданным, если код действительно сложный, а человек/команда его пишущий действительно хорошо понимает тонкости языка.

Однако существовало мнение, что можно оптимизировать небольшие алгоритмы вынося часть кода в натив, именно небольшие алгоритмы которые что-то считают. Особенно выгодно это казалось для android. Но Проведя эти тесты я понял, что как android разработчик без углубленного знания C/C++ я вряд ли смогу написать код который будет быстрее чем на Java, а использование native для простых алгоритмов и вовсе с большой вероятностью не даст ожидаемого результата.

Смыслом статьи хотелось показать, что нет смысла использовать инструмент для микрооптимизаций несложных алгоритмов.

Интересно, каков предел возможностей андроидовского ART. Насколько сложным должен быть алгоритм, чтобы он не смог его оптимизировать и пришлось переходить на С++ и интринсики? Свёртки, IIR, edge detection, median filter ...

Существует такой замечательный сервис - godbolt.org - для сравнения эффективности статических компиляторов. Вот бы что-нибудь подобное для JIT.

Если в build.gradle добавить флаг оптимизации -O3 в строку cppFlags "-fexceptions -O3", то время выполнения с++ и java кода становится +/- одиноаковым, C++ чуть быстрее на устройстве и чуть медленнее в эмуляторе. Это не удивительно, потому что у вас последовательный проход по массиву в цикле - при этом проверки на выход за пределы массива вырезаются. А вот если паттерн доступа будет более сложный, то java код очень сильно проиграет, например, при преобразовании фурье.

высчитывать медиану и пропускать результаты после холодного старта, пока
ЦП не разогреется, я не стал, не вижу в этом смысла в рамках
конкретного исследования

Почему было принято такое решение? Итерации до jit могут быть значительно медленнее и оказать влияние на среднее. Значение вычисления нигде не используется, так что, теоретически, вызов функции может быть и убран компилятором. Стоит ли самому писать усреднение и наталкиваться на проблемы измерения и т.д. если есть инструменты специально для таких сравнений, и например, JMH?

Sign up to leave a comment.