systrace'i anlama

systrace, Android cihaz performansını analiz etmek için kullanılan birincil araçtır. Ancak bu araç, diğer araçlar için bir sarmalayıcıdır. Bu, kullanıcı alanı izlemeyi kontrol eden ve ftrace'i ayarlayan cihaz tarafı yürütülebilir dosya atrace'in ana makine tarafı sarmalayıcısıdır. ftrace ise Linux çekirdeğindeki birincil izleme mekanizmasıdır. systrace, izlemeyi etkinleştirmek için atrace'i kullanır, ardından ftrace arabelleğini okur ve tüm bunları bağımsız bir HTML görüntüleyiciye sarar. (Daha yeni çekirdekler Linux Enhanced Berkeley Packet Filter (eBPF) desteğine sahip olsa da bu sayfada Pixel veya Pixel XL'de kullanılan 3.18 çekirdeği (eFPF yok) ele alınmaktadır.)

systrace, Google Android ve Google Chrome ekiplerine aittir ve Catapult projesi kapsamında açık kaynaklıdır. Catapult, systrace'e ek olarak başka faydalı yardımcı programlar da içerir. Örneğin, ftrace, systrace veya atrace tarafından doğrudan etkinleştirilebilen özelliklerden daha fazlasına sahiptir ve performans sorunlarının hata ayıklanması için kritik olan bazı gelişmiş işlevler içerir. (Bu özellikler için root erişimi ve genellikle yeni bir çekirdek gerekir.)

Systrace'i çalıştırma

Pixel veya Pixel XL'de titreme hata ayıklaması yaparken aşağıdaki komutla başlayın:

./systrace.py sched freq idle am wm gfx view sync binder_driver irq workq input -b 96000

Bu, GPU ve ekran işlem hattı etkinliği için gereken ek izleme noktalarıyla birleştirildiğinde kullanıcı girişinden ekranda gösterilen kareye kadar izleme yapmanıza olanak tanır. Etkinliklerin kaybolmasını önlemek için arabellek boyutunu büyük bir değere ayarlayın (büyük bir arabellek olmadan bazı CPU'lar izlemede bir noktadan sonra etkinlik içermez).

Systrace'i incelerken her etkinliğin CPU'daki bir şey tarafından tetiklendiğini unutmayın.

Systrace, ftrace üzerine kurulduğundan ve ftrace CPU'da çalıştığından, donanım değişikliklerini kaydeden ftrace arabelleğini CPU'da bir şeyin yazması gerekir. Bu, bir ekran çitinin neden durum değiştirdiğini merak ediyorsanız geçişin gerçekleştiği sırada CPU'da neyin çalıştığını görebileceğiniz anlamına gelir (CPU'da çalışan bir öğe, günlükteki bu değişikliği tetiklemiştir). Bu kavram, systrace kullanarak performansı analiz etmenin temelini oluşturur.

Örnek: Çalışma çerçevesi

Bu örnekte, normal bir kullanıcı arayüzü ardışık düzeni için systrace açıklanmaktadır. Örneği takip etmek için izlerin zip dosyasını indirin (bu bölümde bahsedilen diğer izleri de içerir), dosyayı açın ve tarayıcınızda systrace_tutorial.html dosyasını açın.

TouchLatency gibi tutarlı ve periyodik bir iş yükü için kullanıcı arayüzü ardışık düzeni şu sırayı izler:

  1. SurfaceFlinger'daki EventThread, uygulamanın kullanıcı arayüzü iş parçacığını uyandırarak yeni bir kare oluşturma zamanının geldiğini bildirir.
  2. Uygulama, CPU ve GPU kaynaklarını kullanarak kullanıcı arayüzü iş parçacığı, RenderThread ve HWUI görevlerinde bir kare oluşturur. Bu, kullanıcı arayüzü için harcanan kapasitenin büyük bir kısmıdır.
  3. Uygulama, oluşturulan kareyi bir bağlayıcı kullanarak SurfaceFlinger'a gönderir. Ardından SurfaceFlinger uyku moduna geçer.
  4. SurfaceFlinger'daki ikinci bir EventThread, SurfaceFlinger'ı uyandırarak birleştirme ve ekran çıkışını tetikler. SurfaceFlinger yapılacak bir iş olmadığını belirlerse tekrar uyku moduna geçer.
  5. SurfaceFlinger, Hardware Composer (HWC), Hardware Composer 2 (HWC2) veya GL kullanarak birleştirme işlemini gerçekleştirir. HWC ve HWC2 birleştirme işlemi daha hızlıdır ve daha az güç tüketir ancak çip üzerinde sisteme (SoC) bağlı olarak sınırlamaları vardır. Bu işlem genellikle 4-6 ms sürer ancak Android uygulamaları her zaman üçlü arabelleğe alındığından 2. adımla çakışabilir. (Uygulamalar her zaman üçlü arabelleğe alınsa da SurfaceFlinger'da yalnızca bir bekleyen çerçeve olabilir. Bu da çift arabelleğe alma ile aynı görünmesine neden olur.)
  6. SurfaceFlinger, son çıktıyı bir satıcı sürücüsüyle ekrana gönderir ve EventThread'in uyanmasını bekleyerek tekrar uyku moduna geçer.

15409 ms'de başlayan kare dizisi örneğini aşağıda görebilirsiniz:

EventThread çalışırken normal kullanıcı arayüzü ardışık düzeni

1.şekil Normal kullanıcı arayüzü ardışık düzeni, EventThread çalışıyor.

1. şekil, normal karelerle çevrili normal bir karedir. Bu nedenle, kullanıcı arayüzü işlem hattının nasıl çalıştığını anlamak için iyi bir başlangıç noktasıdır. TouchLatency için kullanıcı arayüzü iş parçacığı satırı farklı zamanlarda farklı renkler içeriyor. Çubuklar, ileti dizisinin farklı durumlarını gösterir:

  • Gri. Uyuma
  • Mavi. Çalıştırılabilir (çalıştırılabilir ancak planlayıcı henüz çalıştırmak için seçmemiştir).
  • Yeşil. Etkin olarak çalışıyor (zamanlayıcı, çalışıyor olduğunu düşünüyor).
  • Kırmızı. Kesintisiz uyku (genellikle çekirdekteki bir kilitleme üzerinde uyuma). G/Ç yükünü gösterebilir. Performans sorunlarında hata ayıklama için son derece yararlıdır.
  • Turuncu. G/Ç yükü nedeniyle kesintisiz uyku

Kesintisiz uykunun nedenini görüntülemek için (sched_blocked_reason izleme noktasından kullanılabilir) kırmızı kesintisiz uyku dilimini seçin.

EventThread çalışırken TouchLatency'nin kullanıcı arayüzü iş parçacığı çalıştırılabilir hale gelir. Cihazı neyin uyandırdığını görmek için mavi bölümü tıklayın.

TouchLatency için kullanıcı arayüzü iş parçacığı

Şekil 2. TouchLatency için kullanıcı arayüzü iş parçacığı.

Şekil 2'de, TouchLatency kullanıcı arayüzü iş parçacığının, EventThread'e karşılık gelen tid 6843 tarafından uyandırıldığı gösterilmektedir. Kullanıcı arayüzü iş parçacığı uyanır, bir kare oluşturur ve SurfaceFlinger'in kullanması için sıraya alır.

Kullanıcı arayüzü iş parçacığı uyanır, bir kare oluşturur ve SurfaceFlinger'ın kullanması için sıraya alır.

3.Şekil Kullanıcı arayüzü iş parçacığı uyanır, bir kare oluşturur ve SurfaceFlinger'ın kullanması için sıraya alır.

Bir izlemede binder_driver etiketi etkinse bu işlemde yer alan tüm süreçlerle ilgili bilgileri görüntülemek için bir bağlayıcı işlem seçebilirsiniz.

Ciltleme işlemi

Şekil 4. Ciltleme işlemi.

Şekil 4'te, SurfaceFlinger'daki Binder:6832_1'in 15.423,65 ms'de TouchLatency'nin RenderThread'i olan tid 9579 nedeniyle çalıştırılabilir hale geldiği gösterilmektedir. Ayrıca, bağlayıcı işleminin her iki tarafında da queueBuffer'ı görebilirsiniz.

SurfaceFlinger tarafındaki queueBuffer sırasında TouchLatency'den gelen bekleyen kare sayısı 1'den 2'ye çıkar.

Bekleyen çerçeveler 1 ile 2 arasında değişir.

5.şekil Bekleyen çerçeveler 1 ile 2 arasında değişir.

Şekil 5'te, iki tamamlanmış karenin bulunduğu ve uygulamanın üçüncü kareyi oluşturmaya başlamak üzere olduğu üçlü arabelleğe alma işlemi gösterilmektedir. Bunun nedeni, bazı kareleri zaten bırakmış olmamızdır. Bu nedenle, daha fazla kare bırakılmasını önlemek için uygulama, bekleyen bir kare yerine iki kare tutar.

Kısa bir süre sonra, SurfaceFlinger'ın ana iş parçacığı, eski bekleyen kareyi ekrana çıkış yapabilmesi için ikinci bir EventThread tarafından uyandırılır:

SurfaceFlinger'ın ana iş parçacığı, ikinci bir EventThread tarafından uyandırılıyor

6.şekil SurfaceFlinger'ın ana ileti dizisi, ikinci bir EventThread tarafından uyandırılır.

SurfaceFlinger önce eski bekleyen arabelleği kilitler. Bu durum, bekleyen arabellek sayısının 2'den 1'e düşmesine neden olur:

SurfaceFlinger önce eski bekleyen arabelleğe bağlanır.

Şekil 7. SurfaceFlinger önce eski bekleyen arabelleğe bağlanır.

SurfaceFlinger, arabelleği kilitledikten sonra birleştirme işlemini ayarlar ve son kareyi ekrana gönderir. (Bu bölümlerden bazıları mdssizleme noktasımdss kapsamında etkinleştirildiğinden SoC'nize dahil edilmeyebilir.)

SurfaceFlinger, birleştirme işlemini ayarlar ve son kareyi gönderir.

Şekil 8. SurfaceFlinger, birleştirme işlemini ayarlar ve son kareyi gönderir.

Ardından, mdss_fb0, CPU 0'da uyanır. mdss_fb0, oluşturulan bir kareyi ekrana aktarmak için kullanılan ekran işlem hattının çekirdek iş parçacığıdır. mdss_fb0 öğesinin izlemede kendi satırında olduğunu unutmayın (görüntülemek için aşağı kaydırın):

mdss_fb0, CPU 0'da uyanıyor

Şekil 9. mdss_fb0, CPU 0'da uyanıyor.

mdss_fb0 uyanır, kısa süre çalışır, kesintisiz uykuya girer ve tekrar uyanır.

Örnek: Çalışmayan çerçeve

Bu örnekte, Pixel veya Pixel XL'deki titreme sorununu ayıklamak için kullanılan bir systrace açıklanmaktadır. Örneği takip etmek için izlemelerin ZIP dosyasını indirin (bu bölümde bahsedilen diğer izlemeleri de içerir), dosyayı açın ve tarayıcınızda systrace_tutorial.html dosyasını açın.

Systrace'i açtığınızda aşağıdaki şekle benzer bir şey görürsünüz:

Çoğu seçenek etkin durumdayken Pixel XL'de çalışan TouchLatency

10.şekil Çoğu seçenek etkin durumdayken Pixel XL'de TouchLatency çalıştırılıyor.

Şekil 10'da, mdss ve kgsl izleme noktaları da dahil olmak üzere çoğu seçenek etkinleştirilmiştir.

Jank'ı ararken SurfaceFlinger altındaki FrameMissed satırını kontrol edin. FrameMissed, HWC2 tarafından sağlanan bir yaşam kalitesi iyileştirmesidir. Diğer cihazlar için systrace'i görüntülerken cihaz HWC2'yi kullanmıyorsa FrameMissed satırı mevcut olmayabilir. Her iki durumda da FrameMissed, SurfaceFlinger'ın normal çalışma zamanlarından birini kaçırması ve VSync'te uygulamanın değişmeyen bekleyen arabellek sayısı (com.prefabulated.touchlatency) ile ilişkilidir.

FrameMissed'ın SurfaceFlinger ile korelasyonu

Şekil 11. FrameMissed'in SurfaceFlinger ile korelasyonu.

11. şekilde 15598,29 ms'de kaçırılan bir kare gösterilmektedir. SurfaceFlinger, VSync aralığında kısa bir süre uyandı ve herhangi bir işlem yapmadan tekrar uykuya daldı. Bu, SurfaceFlinger'ın ekrana tekrar kare göndermeyi denemenin değmeyeceğini belirlediği anlamına gelir.

Bu kare için işlem hattının neden bozulduğunu anlamak üzere, normal bir kullanıcı arayüzü işlem hattının systrace'te nasıl göründüğünü görmek için önce yukarıdaki çalışan kare örneğini inceleyin. Hazır olduğunuzda kaçırdığınız kareye dönüp geriye doğru çalışın. SurfaceFlinger'ın uyandığını ve hemen uyku moduna geçtiğini fark edin. TouchLatency'den bekleyen kare sayısını görüntülerken iki kare vardır (ne olduğunu belirlemeye yardımcı olacak iyi bir ipucu).

SurfaceFlinger uyanıyor ve hemen uykuya dalıyor

Şekil 12. SurfaceFlinger uyanıyor ve hemen uyku moduna geçiyor.

SurfaceFlinger'da kareler olduğu için bu bir uygulama sorunu değildir. Ayrıca, SurfaceFlinger doğru zamanda uyandığından bu bir SurfaceFlinger sorunu değildir. SurfaceFlinger ve uygulama normal görünüyorsa sorun muhtemelen sürücüyle ilgilidir.

mdss ve sync izleme noktaları etkinleştirildiğinden, karelerin ekrana ne zaman gönderileceğini kontrol eden bariyerler (ekran sürücüsü ve SurfaceFlinger arasında paylaşılır) hakkında bilgi edinebilirsiniz. Bu çitler, bir çerçevenin ekranda ne zaman olduğunu gösteren mdss_fb0_retire altında listelenir. Bu sınırlar, sync iz kategorisinin bir parçası olarak sağlanır. SurfaceFlinger'daki belirli olaylara hangi bariyerlerin karşılık geldiği, çip üzerinde sisteminize ve sürücü yığınına bağlıdır. Bu nedenle, izlerinizdeki bariyer kategorilerinin anlamını anlamak için çip üzerinde sistem tedarikçinizle birlikte çalışın.

mdss_fb0_retire fences

Şekil 13. mdss_fb0_retire fences.

Şekil 13'te, beklendiği gibi 16,7 ms değil, 33 ms boyunca görüntülenen bir kare gösteriliyor. Bu dilimin yarısında, söz konusu karenin yenisiyle değiştirilmesi gerekirdi ancak değiştirilmedi. Önceki kareyi görüntüleyip herhangi bir şeyi arayın.

Bozuk kareden önceki kare

Şekil 14. Kırık çerçeveden önceki çerçeve.

Şekil 14'te 14.482 ms'lik bir kare gösterilmektedir. Bozuk iki karelik segment 33,6 ms sürdü. Bu süre, iki kare için yaklaşık olarak beklenen süredir (60 Hz'de oluşturulan kareler, kare başına 16,7 ms sürer ve bu süreye yakındır). Ancak 14.482 ms, 16,7 ms'ye yakın olmadığından ekran hattında bir sorun olduğu anlaşılıyor.

Bu çitin tam olarak nerede bittiğini araştırarak hangi kontrollerin geçerli olduğunu belirleyin:

Çitin sonunu inceleme

Şekil 15. Çitin sonunu inceleyin.

Bir iş sırası, bariyer değiştiğinde çalışan __vsync_retire_work_handler içerir. Çekirdek kaynağına baktığınızda bunun ekran sürücüsünün bir parçası olduğunu görebilirsiniz. Görüntüleme ardışık düzeninin kritik yolunda olduğu için mümkün olduğunca hızlı çalışması gerekir. Yaklaşık 70 μsn boyunca çalıştırılabilir (uzun bir planlama gecikmesi değildir) ancak bir iş sırası olduğundan doğru şekilde planlanmayabilir.

Bunun katkısı olup olmadığını belirlemek için önceki kareyi kontrol edin. Bazen titreme zamanla artabilir ve sonunda son tarihin kaçırılmasına neden olabilir:

Önceki kare

16.şekil Önceki kare.

Görüntüleyici, seçildiğinde kworker'daki çalıştırılabilir satırı beyaz renge dönüştürdüğü için bu satır görünmüyor.Ancak istatistikler durumu açıklıyor: Ekran işlem hattının kritik yolunun bir bölümünde 2,3 ms'lik planlayıcı gecikmesi kötü. Devam etmeden önce, bu bölümü görüntüleme işlem hattı kritik yolundan bir iş kuyruğundan (SCHED_OTHER CFS iş parçacığı olarak çalışır) özel bir SCHED_FIFO kthread'e taşıyarak gecikmeyi düzeltin. Bu işlev, workqueue'ların sağlayamayacağı (ve sağlaması amaçlanmadığı) zamanlama garantilerine ihtiyaç duyar.

Bu durumun takılmaya neden olduğu açıkça anlaşılmıyor. Görüntüleme açısından kritik iş parçacıklarının uyumasına neden olan çekirdek kilidi çekişmesi gibi kolayca teşhis edilebilen durumlar dışında, izler genellikle sorunu belirtmez. Bu titreme, bırakılan karenin nedeni olabilir. Çit süreleri 16, 7 ms olmalıdır ancak bırakılan kareye kadar olan karelerde bu süreye hiç yaklaşılmaz. Ekran işlem hattının ne kadar sıkı bir şekilde bağlı olduğu göz önüne alındığında, çit zamanlamalarındaki titremenin bir kare düşmesine neden olması mümkündür.

Bu örnekte çözüm, __vsync_retire_work_handler öğesini bir iş kuyruğundan özel bir kthread'e dönüştürmeyi içerir. Bu, zıplayan top testinde fark edilebilir titreme iyileştirmeleri ve azaltılmış sarsıntı ile sonuçlanır. Sonraki izlemelerde, 16,7 ms'ye çok yakın olan çit zamanlamaları gösteriliyor.