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

Интерпретация многоуровневой трассировки производительности (Eclipse/Android)

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

Мое приложение имеет 3 потока:

  • поток пользовательского интерфейса (должен быть в основном неактивным)
  • Игровая логическая тема
  • Графическая тема

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

Однако, как только я добрался до реализации, моя работа заняла большое место. Это намного хуже, чем раньше, один цикл обновления и рендеринга занимает примерно 50 мс (20 кадров в секунду), поэтому он выглядит как мусор. Это всего лишь рендеринг примерно 20 треугольников и, возможно, 20 текстурированных квадратов, действительно простая рабочая нагрузка (я боюсь думать о том, что будет, когда я реализую правильную графику).

В любом случае я взял трассировку DDMS в андроиде в профиль, где дела идут неправильно или могут быть улучшены.

trace1http://i.stack.imgur.com/DDUYE.png

Это примерно 3 кадра моей игры. Пока что, похоже, примерно то, что я ожидал. Части, выделенные синим цветом, представляют собой заблокированную секцию, которая выглядит правильно (держит glThread в основном, ожидая, пока он заблокирован). Однако как только я разблокирую его, я должен видеть, что оба потока работают одновременно, и похоже, что они есть, но если я посмотрю ближе:

trace2http://i.stack.imgur.com/vukXQ.png

Я занимаюсь разработкой на двухъядерном телефоне, но если я правильно понимаю трассировку, это не похоже на то, что он когда-либо делал что-либо параллельно, и что хуже, по-видимому, переключает активную нить сотни раз за миллисекунды! (если я не интерпретирую это неправильно). Все это переключение контекста, похоже, было бы ужасно для производительности, поэтому я не уверен, почему он хотел бы переключаться туда и обратно так быстро.

Итак, после моего долгого объяснения, мне интересно несколько вещей:

  • Насколько я понимаю, что заполненные прямоугольники в трассировке являются активными потоками, а цветные линии - спящими потоками? В противном случае, что они означают?
  • Почему я не вижу, чтобы мои потоки выполнялись одновременно на якобы двухъядерном телефоне?
  • Почему это так быстро переключает активные потоки?
  • В DDMS я получаю предупреждение "ПРЕДУПРЕЖДЕНИЕ: активен отладчик, результаты отслеживания методов будут искажены". О чем это беспокоиться? Как я могу избавиться от этого предупреждения? (Я запускал приложение через Run, а не через Debug, если это имеет значение)
4b9b3361

Ответ 1

Очень хороший вопрос, позвольте мне начать с ответов:

  • Вы перепутали потоки/методы/activeMethod. Каждая строка в traceview представляет собой поток (и если вы назвали свои потоки, вы увидите это имя на левой стороне, например, "GL Thread", "main" и т.д.). Прямоугольники (цветные) представляют активные методы выполнения внутри каждого потока, в то время как цветные линии представляют собой "приостановленные" методы внутри потока. Под "приостановленным" я подразумеваю, что "метод все еще выполняется, но контекст был переключен на какой-то другой поток, и когда контекст снова переключился на этот поток, этот метод будет продолжать работать. В терминологии, которую вы использовали в своем вопросе, линии - это методы спящего потока, а прямоугольник - активный метод выполнения потока. Вы можете найти дополнительную информацию о отслеживании DDMS здесь.
  • Распределение потоков между ядрами - это еще одна история и в значительной степени зависит от основных механизмов ОС Android. Прежде всего, убедитесь, что целевая ОС Android запущена с опцией SMP (Symmetric Multi-Processing), которая по умолчанию используется для многоядерных телефонов, я думаю:), но я не разбираюсь в этих вещах. Несколько слов о SMP вы можете найти здесь.
  • Переключение потоков зависит от OS Thread/Process scheduler, приоритета потока и т.д. Подробнее об этом можно найти в этих ответах.
  • Даже если вы запустили приложение в режиме без отладки, когда вы подключаетесь к DDMS и выполняете такие функции, как профилирование методов, вы активируете отладочные части davlik vm. Подробнее об отладке здесь, раздел "Реализация".

Надеюсь, этот ответ вам поможет.

Ответ 2

Спасибо за вопрос. Мне тоже будет полезен полный ответ инсайдера. Я скажу то, что знаю.

  • Некоторые (все?) телефоны имеют возможность включить/отключить второе ядро. Вы проверили, что ваш включен?

  • В моем собственном приложении я заметил, что просто переход из одного потока в два (по одному ядру) без изменения общей работы, вызванной фактором замедления в 1,5 раза, поэтому очень важно, чтобы потоковая передача имела стоимость.

  • Именно в новостях Intel обращается к Google с плохой реализацией многоядерной потоковой передачи:

    http://www.pcworld.com/article/257307/dual_core_processors_wasted_on_android_intel_claims.html

    Ваши результаты подтверждают это.

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