Значение сообщений хореографа в Logcat [дубликат]


этот вопрос уже есть ответ здесь:

Я установил последние версии SDK (API 16) и получил последний ADT. Теперь я вижу эти сообщения в logcat, что я совершенно уверен, я не видел раньше. Кто-нибудь имеет представление о это?

06-29 23:11:17.796: я / хореограф(691): пропущено 647 кадров! Этот приложение может делать слишком много работы на основной поток.

Я сделал поиск и нашел эту ссылку: http://developer.android.com/reference/android/view/Choreographer.html. это новый класс, введенный в API 16.

мне нужно знать как я могу определить, что "слишком много работы" мне может быть делать как все мои обработку в AsyncTasks.

5 192

5 ответов:

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

Android view animations внутренне использует хореографа для той же цели: правильно настроить анимацию и, возможно, улучшить производительность.

поскольку хореограф рассказывается о каждом событии vsync, я могу сказать, прошел ли один из Runnables хореографом.post * API не заканчивается за один кадр, в результате чего кадры будут пропущенный.

в моем понимании хореограф может только обнаружить пропуск кадра. Он не может сказать, почему это происходит.

сообщением "приложение может делать слишком много работы на основной поток.- это может ввести в заблуждение.

Я опаздываю на вечеринку, но, надеюсь, это полезное дополнение к другим ответам здесь...

отвечая на вопрос / tl: dr;

мне нужно знать, как я могу определить, что "слишком много работы" мое приложение может делать, поскольку вся моя обработка выполняется в AsyncTasks.

ниже перечислены все кандидаты:

  • IO или дорогостоящая обработка в основном потоке (загрузка чертежей, раздувание макетов и т. д установка Uriна ImageView'S Все составляющие ввода-вывода в основном потоке)
  • рендеринг большой / сложный / глубокий View иерархия
  • аннулирование больших частей a View иерархия
  • дорого onDraw методы в custom View ' s
  • дорогие расчеты в анимации
  • запуск" рабочих "потоков с слишком высоким приоритетом, чтобы считаться "фоном" (AsyncTask ' s являются "фоном" по умолчанию,java.lang.Thread is не)
  • создание большого количества мусора, в результате чего сборщик мусора "остановить мир" - в том числе основной поток - в то время как он очищает

на самом деле определить конкретная причина, по которой вам нужно будет профилировать свое приложение.

Более Подробно

Я пытался понять хореографа, экспериментируя и глядя на код.

документация хореографа открывается с помощью " координаты времени анимации, ввода и рисования."что на самом деле является хорошим описанием, но остальное продолжает подчеркивать анимацию.

хореограф фактически отвечает за исполнение 3 типов обратных вызовов, которые выполняются в следующем порядке:

  1. обратные вызовы обработки ввода (обработка пользовательского ввода, такого как события касания)
  2. анимация обратных вызовов для tweening между кадрами, обеспечивая стабильное время начала кадра для любого/всех анимация, которая выполняется. Выполнение этих обратных вызовов 2-го означает, что любые вычисления, связанные с анимацией (например, изменение позиций представления), уже были сделаны к моменту вызова третьего типа обратного вызова...
  3. просмотр обратных вызовов обхода для рисования иерархии видов.

цель состоит в том, чтобы соответствовать скорости, с которой недействительные представления повторно рисуются (и анимации tweened) с экраном vsync-обычно 60fps.

предупреждение о пропущенных кадры выглядят как запоздалая мысль: сообщение регистрируется, если один прохождение через 3 шага занимает более 30x ожидаемой продолжительности кадра, поэтому наименьшее число, которое вы можете ожидать увидеть в сообщениях журнала, - " пропущено 30 кадры"; если каждого проход занимает на 50% больше времени, чем следует вы все равно пропустите 30 кадров (шалить!) но вы не будете об этом предупреждены.

из 3 шагов ясно, что это не только анимации, которые могут вызвать предупреждение: аннулирование значительной части большого View иерархия или a View со сложным методом onDraw может быть достаточно.

например, это вызовет предупреждение несколько раз:

public class AnnoyTheChoreographerActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.simple_linear_layout);

        ViewGroup root = (ViewGroup) findViewById(R.id.root);

        root.addView(new TextView(this){
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                long sleep = (long)(Math.random() * 1000L);
                setText("" + sleep);
                try {
                    Thread.sleep(sleep);
                } catch (Exception exc) {}
            }
        });
    }
}

... который производит ведение журнала, как это:

11-06 09:35:15.865  13721-13721/example I/Choreographer﹕ Skipped 42 frames!  The application may be doing too much work on its main thread.
11-06 09:35:17.395  13721-13721/example I/Choreographer﹕ Skipped 59 frames!  The application may be doing too much work on its main thread.
11-06 09:35:18.030  13721-13721/example I/Choreographer﹕ Skipped 37 frames!  The application may be doing too much work on its main thread.

вы можете видеть из стека во время onDraw что хореограф участвует независимо от того, анимируете ли вы:

at образец.AnnoyTheChoreographerActivity$1.onDraw (AnnoyTheChoreographerActivity.Ява:25) на Андроид.вид.Вид.ничья(вид.java: 13759)

... довольно много повторений ...

на android.вид.ViewGroup.drawChild(ViewGroup.java:3169) на Андроид.вид.ViewGroup.dispatchDraw(ViewGroup.java:3039) на Андроид.вид.Вид.ничья(вид.java: 13762) на Андроид.штучка.Так.рисовать(так.java: 467) на com.андроид.внутренний.политика.осущ.PhoneWindow$DecorView.draw(PhoneWindow.java: 2396) на Андроид.вид.Вид.getDisplayList (View.java: 12710) на Андроид.вид.Вид.getDisplayList (View.java: 12754) на Андроид.вид.HardwareRenderer$GlRenderer.ничья(HardwareRenderer.java: 1144) на Андроид.вид.ViewRootImpl.ничья(ViewRootImpl.java: 2273) на Андроид.вид.ViewRootImpl.performDraw(ViewRootImpl.java: 2145) на Андроид.вид.ViewRootImpl.performTraversals(ViewRootImpl.java: 1956) на андроид.вид.ViewRootImpl.doTraversal (ViewRootImpl.java: 1112) на Андроид.вид.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4472) на android.вид.Хореограф$CallbackRecord.беги(хореограф.java:725) на Андроид.вид.Хореограф.doCallbacks (хореограф.java: 555) на Андроид.вид.Хореограф.дофраме(хореограф.java:525) на Андроид.вид.Хореограф$FrameDisplayEventReceiver.беги(хореограф.java: 711) на андроид.ОС.Обработчик.handleCallback (обработчик.java:615) на Андроид.ОС.Обработчик.dispatchMessage(обработчика.Ява:92) на Андроид.ОС.Петлитель.петля(Looper.java: 137) на Андроид.приложение.ActivityThread.main (ActivityThread.java: 4898)

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

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

Это если информационное сообщение, которое может появиться в вашем LogCat во многих ситуациях.

в моем случае это произошло, когда я раздувал несколько представлений из файлов макета XML программно. Сообщение безобидно само по себе, но может быть признаком более поздней проблемы, которая будет использовать всю оперативную память, которую ваше приложение может использовать, и вызвать близкую силу мега-зла. Я вырос, чтобы быть таким разработчиком, который любит видеть его журнал предупреждать/информация/без ошибок. ;)

Итак, это мой собственный опыт:

Я получил сообщение:

10-09 01:25:08.373: I/Choreographer(11134): Skipped XXX frames!  The application may be doing too much work on its main thread.

... когда я создавал свой собственный "супер-сложный многосекционный список", раздувая представление из XML и заполняя его поля (изображения, текст и т. д...) с данными, поступающими из ответа веб-службы REST/JSON( без возможности подкачки), эти представления будут действовать как строки, заголовки подразделов и заголовки разделов, добавляя их все в правильном порядке в LinearLayout (с вертикальной ориентацией внутри a ScrollView). Все это для имитации listView с интерактивными элементами... но это уже другой вопрос.

как ответственный разработчик вы хотите сделать приложение действительно эффективным с системными ресурсами, поэтому лучшая практика для списков (когда ваши списки не так сложны) - использовать ListActivity или ListFragment с загрузчиком и заполнить ListView адаптером, это якобы более эффективно, на самом деле это так, и вы должны делать это все время, снова... если ваш список не так уж и сложно.

решение: я реализовал подкачку на своем веб-сервисе REST/JSON, чтобы предотвратить "большие размеры ответа", и я завернул код, который добавил представления "строки", "заголовки разделов" и "заголовки подразделов" в AsyncTask, чтобы сохранить основной поток прохладным.

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

всего доброго!

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

в моем случае у меня есть эти сообщения, когда я показываю панель действий Шерлока inderterminate progressbar. Так как это не моя библиотека, я решил скрыть выходы хореографа.

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

tag:^((?!Хореограф.)* )$

Я использовал регулярное выражение, объясненное в другом месте:регулярное выражение, чтобы соответствовать строку, которая не содержит слово?