Подтвердить что ты не робот

Какую оптимизацию я могу ожидать от Dalvik и инструментальной цепочки Android?

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

Отсюда этот вопрос. Я мог найти очень мало об этой теме в Интернете. Будет ли компилятор Java, конвертер Dalvik (dx) и/или JITter (на Android 2.2+) выполнять оптимизации, например, следующие:

  • Встраивание метода. При каких условиях? private методы всегда могут быть смещены; это будет сделано? Как насчет методов public final? Методы на объектах других классов? static методы? Что делать, если тип выполнения объекта может быть легко выведен компилятором? Должен ли я объявлять методы как final или static по возможности?

  • Исключение общего подвыражения. Например, если я дважды получаю доступ к someObject.someField, поиск будет выполняться только один раз? Что, если это вызов геттеру? Что делать, если я использую некоторое арифметическое выражение дважды; будет ли он оцениваться только один раз? Что делать, если я использую результат некоторого выражения, значение которого я не знаю, как верхнюю границу цикла for?

  • Проверка границ поиска массива. Остановит ли эта цепочка в определенных условиях, как архетипическая петля for?

  • Вставка значений. Будет ли доступ к некоторым public static final int всегда включенным? Даже если они в другом классе? Даже если они находятся в другом пакете?

  • Прогнозирование ветвей. Насколько это важно? Является ли ветвление большим успехом на обычном устройстве Android?

  • Простая арифметика. Будет ли заменен someInt * 2 на someInt << 1?

Etcetera...

4b9b3361

Ответ 1

Это Бен, один из инженеров, работающих над JIT @Google. Когда мы с Биллом начали работать над этим проектом, цель заключалась в том, чтобы как можно скорее доставить рабочую JIT с минимальным воздействием на конфликт ресурсов (например, объем памяти, процессор, захваченный потоком компилятора), чтобы он мог работать на младших устройствах, Что ж. Поэтому мы использовали очень примитивную модель на основе трассировки. То есть объект компиляции, переданный компилятору JIT, является базовым блоком, иногда коротким, как одна команда. Такие трассы будут сшиты во время выполнения с помощью метода, называемого цепочкой, так что поиск интерпретатора и кода не будет часто вызываться. В какой-то степени основным источником ускорения является устранение излишней обработки синтаксического анализа повторного интерпретатора на часто исполняемых кодах кода.

Тем не менее, у нас есть довольно много локальных оптимизаций, реализованных с Froyo JIT:

  • Регистрировать распределение (8 регистров для цели v5te, так как JIT производит код Thumb/16 регистров для v7)
  • Планирование (например, избыточное удаление ld/st для регистров Dalvik, загрузка груза, погружение в хранилище)
  • Исключение избыточной нулевой проверки (если такая избыточность может быть найдена в базовом блоке).
  • Формирование и оптимизация цикла для простых счетных циклов (то есть без бокового выхода в теле цикла). Для таких циклов массивные обращения на основе расширенных переменных индукции оптимизируются таким образом, что проверки нулей и диапазонов выполняются только в прологе цикла.
  • Один встроенный кэш на виртуальный call-сайт с динамическим исправлением во время выполнения.
  • Оптимизации Peephole, такие как уменьшение мощности в буквальных операндах для mul/div.

В Gingerbread мы добавили простую вставку для getters/seters. Поскольку базовый интерфейс JIT по-прежнему является простым основанием на трассировке, если у вызываемого есть ветки, он не будет встроен. Но встроенный механизм кэширования реализован так, что виртуальные геттеры/сеттеры могут быть встроены без проблем.

В настоящее время мы работаем над расширением области компиляции за простой трассировкой, чтобы у компилятора было большее окно для анализа и оптимизации кода. Оставайтесь с нами.

Ответ 2

Я уверен, что мой ответ не ответит на все ваши вопросы, но я думаю, что это победа, если он отвечает даже на один.

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

Возьмите APK, который вы получите, и запустите его с помощью APK Tool. Обратное проектирование вашего собственного кода, чтобы сделать то, что вы намереваетесь, прекрасно, как мы знаем.

APK Tool будет извлекать и декодировать ваши ресурсы и реверсировать файлы .dex в файлы .smali. Возможно, вам захочется найти проект smali, чтобы получить дополнительную информацию о том, как читать файлы .smali и о его ограничениях.

Снова я уверен, что это не будет отвечать на все ваши вопросы, но это может быть хорошим началом.

Ответ 3

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

  • Метод inlining - насколько мне известно, этого никогда не происходит. Я почти уверен, что это никогда не происходит на уровне байт-кода, и я не думаю, что это происходит на уровне JIT в настоящее время - хотя это возможно и в будущем.

  • Исключение общего подвыражения - я считаю, что это будет сделано только для подвыражений, которые не используют какие-либо не конечные переменные/поля. Я не совсем уверен, если это произойдет даже тогда. Если это будет сделано, я ожидаю, что это будет сделано на уровне байт-кода, возможно, не на уровне JIT.

  • Проверка ссылок на поиск массива - нет подсказки

  • Вложение значений - насколько я знаю, да - они будут включены во все эти сценарии.

  • Прогнозирование ветки - не уверен

  • Простая арифметика - не насколько я знаю

Кроме того, я хотел бы упомянуть еще один подход к вам - dx и dalvik - оба с открытым исходным кодом, поэтому вы можете в них копать все, что вам нравится. Хотя, очевидно, это не маленькие кодовые базы, поэтому потребовалось бы немного усилий, чтобы копаться в них на этом уровне.