Как понять трассировку профиля Android SDK?

У меня есть код, который использует Jsoup для получения и анализа некоторых html-страниц, а затем я манипулирую html-деревом, прежде чем передать его в WebView, который его рисует. Если я обойду мои манипуляции, код будет выполняться за приемлемое время (2-3 секунды) на симуляторе Android SDK, но когда я выполняю свои манипуляции, время будет недопустимым (~ 60 секунд, чтобы просто загрузить одну страницу!).

Используя Eclipse и Android SDK, я профилировал запуск, и теперь я пытаюсь интерпретировать результаты. отсюда http://android-developers.blogspot.com/2010/10/traceview-war-story.html воспользовался советом, чтобы отсортировать профиль по «Эксклюзивному процессорному времени %». К моему удивлению, мой собственный код даже не попал в список 1%. Самый большой потребитель времени — android.view.ViewGroup.drawChild() — 11,9%. Первая перечисленная функция, не относящаяся к Android (отсортированная по эксклюзивному процессорному процессору%), — это java.lang.ref.Reference.get(), и она указана как 0,4%.

Но я думаю, что самое странное - это мой собственный код, я могу найти только doInBackground() моего AsyncTask в списке; функции, которые это вызывает, в свою очередь, даже не присутствуют, хотя я вижу по отладочному выводу, что они вызываются. Почему таких нет в списке?

Я не понимаю, что со всем этим делать. Любые подсказки очень ценятся.


person OppfinnarJocke    schedule 19.01.2012    source источник
comment
Если кому-то интересно... оказывается, здесь виноват AsyncTask, а не мой код. Глядя на окно TraceView, я только сейчас понял, что моя задача запускалась очень редко, примерно 4 раза в секунду фрагментами по 10 мс! По умолчанию приоритет потока был равен 5, теперь я установил его на Thread.MAX_PRIORITY, и теперь я приближаюсь к приемлемому времени загрузки, 10 секунд вместо предыдущих 60+ секунд. Теперь интересно, это я или так должно работать...?   -  person OppfinnarJocke    schedule 21.01.2012


Ответы (1)


Хотя у меня нет под рукой ссылки, я думаю, можно с уверенностью предположить, что Android выполняет AsyncTask.doInBackground() в потоке с приоритетом android.os.Process.THREAD_PRIORITY_BACKGROUND

Это означает, что этот поток запланирован в контексте cgroup Linux (класса планирования), для которого — всегда или при частых обстоятельствах, я не уверен и читал различные утверждения — верхняя граница общего времени процессора составляет 5% или 10% — опять же, разные источники делают разные заявления — применяется.

Другими словами, все фоновые потоки должны совместно использовать 5% или 10% доступного процессорного времени. Опять же, я читал заявления о том, что это динамически корректируется, если задачи переднего плана и реального времени простаивают, но я был бы рад, если бы мне указали на достоверный источник. Кроме того, я бы не стал на это рассчитывать, поскольку пользователь может слушать аудиопоток в реальном времени при использовании моего приложения.

Если вы настроите приоритет фонового потока, например:

private static final int bgThreadPrio = Process.THREAD_PRIORITY_BACKGROUND +
                                        Process.THREAD_PRIORITY_MORE_FAVORABLE;
protected YourReturnType doInBackground() {
    Process.setThreadPriority(bgThreadPrio);
    ....
}

тогда вы достигнете двух вещей.

  • Вы поднимаете поток из фоновой контрольной группы, чтобы ему не приходилось делить 10% процессорного времени с другими фоновыми потоками (по крайней мере, в настоящее время, пока Android не изменит свою политику в этом отношении).
  • Вы назначаете приоритет потоку, который обычно не будет иметь очень плохого влияния на потоки пользовательского интерфейса и реального времени, потому что THREAD_PRIORITY_DEFAULT равен 0, а THREAD_PRIORITY_BACKGROUND равен 10. Таким образом, ваш поток будет работать с приоритетом 9, что намного хуже, чем 0, но он будет избежать искусственного ограничения фоновых задач.

Однако вы также, вероятно, измените приоритет потока, который базовый исполнитель AsyncTask предоставляет для вашей AsyncTask. Этот поток будет переработан, и это может быть один поток или выбранный из пула. Поэтому может быть хорошей идеей установить приоритет во всех методах doInBackground() во всех AsyncTasks в вашем приложении.

person class stacker    schedule 08.01.2013