Я изучаю производительность своего приложения, так как заметил, что оно пропускает несколько кадров при прокрутке. Я запустил systrace (на Nexus 4 с версией 4.3) и заметил интересный раздел в выводе.
Сначала все хорошо. Увеличение слева, мы видим, что отрисовка начинается при каждой вертикальной синхронизации, заканчивается с запасом времени и ожидает следующей вертикальной синхронизации. Поскольку он имеет тройную буферизацию, он должен отрисовываться в буфер, который будет отправлен на следующую вертикальную синхронизацию после того, как это будет сделано.
На 4-й вертикальной синхронизации на увеличенном снимке экрана приложение выполняет некоторую работу, и операция рисования не завершается вовремя для следующей вертикальной синхронизации. Однако мы не пропускаем ни одного кадра, потому что предыдущие отрисовки работали на кадр вперед.
Однако после этого операции отрисовки не компенсируют пропущенную вертикальную синхронизацию. Вместо этого запускается только одна операция отрисовки за вертикальную синхронизацию, и теперь они больше не отрисовывают на один кадр вперед.
Увеличение справа разделе, приложение выполняет дополнительную работу и пропускает еще одну вертикальную синхронизацию. Так как мы не рисовали кадр вперед, здесь фактически пропускается кадр. После этого он возвращается к рисованию на один кадр вперед.
Это ожидаемое поведение? Насколько я понимаю, тройная буферизация позволяла вам восстанавливаться, если вы пропустили вертикальную синхронизацию, но такое поведение выглядит так, будто она пропускает кадр один раз каждые две пропущенные вертикальные синхронизации.
Последующие вопросы
В правой части этого снимка экрана приложение фактически обрабатывает буферы быстрее, чем дисплей потребляет их. Предположим, что во время выполнения #1 (обозначено на скриншоте) буфер A отображается, а буфер B визуализируется. #1 завершается задолго до вертикальной синхронизации и ставит буфер B в очередь. На данный момент, разве приложение не должно иметь возможность немедленно начать рендеринг буфера C? Вместо этого PerformTraversals #2 не запускается до следующей вертикальной синхронизации, что приводит к потере драгоценного времени между ними.
Точно так же я немного смущен необходимостью waitForever здесь слева. Допустим, буфер A отображается, буфер B находится в очереди, а буфер C обрабатывается. Когда буфер C завершает рендеринг, почему он сразу не добавляется в очередь? Вместо этого он выполняет waitForever до тех пор, пока буфер B не будет удален из очереди, и в этот момент он добавляет буфер C, поэтому очередь, кажется, всегда остается в размере 1, независимо от того, насколько быстро приложение обрабатывает буферы.