Чтобы использовать JNI или не использовать JNI (производительность Android)

Я только что добавил вычислительно затратный код в разрабатываемую мной игру для Android. Рассматриваемый код представляет собой набор коллизий процедуры обнаружения, которые вызываются очень часто (каждая итерация игрового цикла) и выполняют большой объем вычислений. Я считаю, что моя реализация обнаружения столкновений достаточно хорошо разработана и настолько быстро, насколько я могу сделать это на Java.

Я использовал Traceview для профилирования кода, и этот новый фрагмент кода обнаружения столкновений несколько неудивительно удвоил продолжительность моей игровой логики. Это, очевидно, вызывает беспокойство, поскольку для некоторых устройств это снижение производительности может перевести мою игру из игрового в неиграбельное состояние.

Я обдумывал различные способы оптимизации этого кода, и мне интересно, если, переместив код в C ++ и получив к нему доступ с помощью JNI, я получу заметные е экономия производительности?

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

  • Это сделает код чище.Поскольку большая часть обнаружения столкновений - это своего рода векторная математика, гораздо проще иметь возможность использовать перегруженные операторы, а не использовать более подробные векторные классы в Java.

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

Многословный, поскольку этот вопрос может быть, я думаю, что осветил все свои вопросы. Учитывая эту информацию, стоит ли переносить мой код с Java на C ++ и обращаться к нему с помощью JNI (в целях повышения производительности)? Кроме того, есть ли способ измерить или оценить потенциальный прирост производительности?

РЕДАКТИРОВАТЬ:

Итак, я это сделал. Полученные результаты? Что ж, с точки зрения TraceView, скорость моей процедуры обнаружения столкновений увеличилась в 6 раз.

Но попасть туда было непросто. Помимо того, что мне пришлось танцевать JNI, мне также пришлось внести некоторые оптимизации, которых я не ожидал. В основном, использование непосредственно выделенного буфера с плавающей запятой для передачи данных из Java в родной. Моя первоначальная попытка просто использовала массив с плавающей запятой для хранения рассматриваемых данных, потому что преобразование из Java в C ++ было более естественным, но действительно очень медленным. Прямой буфер полностью обошел стороной проблемы с производительностью при копировании массива между java и native и оставил мне 6-кратный удар.

Кроме того, вместо того, чтобы использовать собственный векторный класс, я просто использовал математическую библиотеку Eigen. Я не уверен, насколько это повлияло на производительность, но, по крайней мере, это сэкономило мне время на разработку собственного (менее эффективного) векторного класса.

Другой извлеченный урок заключается в том, что чрезмерное ведение журнала плохо сказывается на производительности (jic, это не очевидно).

11
задан user8709 1 February 2012 в 09:43
поделиться