Performans testi

Android 8.0, aktarım hızı ve gecikme süresi için binder ve hwbinder performans testleri içerir. Belirgin performans sorunlarını tespit etmek için birçok senaryo olsa da bu tür senaryoları çalıştırmak zaman alıcı olabilir ve sonuçlar genellikle bir sistem entegre edilene kadar kullanılamaz. Sağlanan performans testlerini kullanmak, geliştirme sırasında test yapmayı, ciddi sorunları daha erken tespit etmeyi ve kullanıcı deneyimini iyileştirmeyi kolaylaştırır.

Performans testleri aşağıdaki dört kategoriyi içerir:

  • bağlayıcı işleme hızı (system/libhwbinder/vts/performance/Benchmark_binder.cpp sürümünde kullanılabilir)
  • bağlayıcı gecikmesi (frameworks/native/libs/binder/tests/schd-dbg.cpp'te kullanılabilir)
  • hwbinder işleme hızı (system/libhwbinder/vts/performance/Benchmark.cpp'te kullanılabilir)
  • hwbinder gecikmesi (system/libhwbinder/vts/performance/Latency.cpp'te kullanılabilir)

binder ve hwbinder hakkında

Binder ve hwbinder, aynı Linux sürücüsünü paylaşan ancak aşağıdaki niteliksel farklılıklara sahip Android işlemler arası iletişim (IPC) altyapılarıdır:

En Boy Oranı cilt hwbinder
Amaç Çerçeve için genel amaçlı bir IPC şeması sağlayın Donanımla iletişim kurma
Özellik Android çerçevesi kullanımı için optimize edilmiş Minimum ek yük, düşük gecikme
Ön plan/arka plan için planlama politikasını değiştirme Evet Hayır
Bağımsız değişkenleri aktarma Paket nesnesi tarafından desteklenen serileştirmeyi kullanır. Paket serileştirme için gerekli verileri kopyalamayla ilgili ek maliyeti önlemek amacıyla dağınık arabellekleri kullanır.
Öncelikli devralma Hayır Evet

Binder ve hwbinder işlemleri

Bir systrace görselleştiricisi işlemleri aşağıdaki gibi gösterir:

Şekil 1. Bağlayıcı işlemlerinin Systrace görselleştirmesi.

Yukarıdaki örnekte:

  • Dört (4) schd-dbg işlemi istemci işlemleridir.
  • Dört (4) bağlayıcı işlemi sunucu işlemidir (ad Binder ile başlar ve bir sıra numarasıyla biter).
  • İstemci işlemleri her zaman istemciye özel bir sunucu işlemiyle eşlenir.
  • Tüm istemci-sunucu işlem çiftleri, çekirdek tarafından eşzamanlı olarak bağımsız olarak planlanır.

1. CPU'da işletim sistemi çekirdeği, isteği göndermek için istemciyi yürütür. Ardından, mümkün olduğunda aynı CPU'yu kullanarak bir sunucu sürecini uyandırır, isteği işler ve istek tamamlandıktan sonra bağlam geçişini geri yapar.

İşleme hızı ve gecikme

İstemci ve sunucu işleminin sorunsuz bir şekilde geçiş yaptığı mükemmel bir işlemde, aktarım hızı ve gecikme testi önemli ölçüde farklı mesajlar üretmez. Ancak OS çekirdeği, donanımdan gelen bir kesinti isteğini (IRQ) işlediğinde, kilitleri beklediğinde veya bir mesajı hemen işlemeyi tercih etmediğinde gecikme balonu oluşabilir.

Şekil 2. Aktarım hızı ve gecikmedeki farklılıklar nedeniyle gecikme balonu.

Veri akışı testi, farklı yükü boyutlarına sahip çok sayıda işlem oluşturur. Böylece, normal işlem süresi (en iyi senaryoda) ve bağlayıcının elde edebileceği maksimum veri akışı için iyi bir tahmin sağlanır.

Buna karşılık, gecikme testi normal işlem süresini en aza indirmek için yükü üzerinde herhangi bir işlem gerçekleştirmez. Bağlayıcı yükü tahmin etmek, en kötü durum için istatistikler oluşturmak ve gecikmesi belirtilen son tarihe uyan işlemlerin oranını hesaplamak için işlem süresini kullanabiliriz.

Öncelik tersine çevirme işlemlerini ele alma

Önceliğin ters dönmesi, mantıksal olarak daha yüksek öncelikli bir iş parçacığı daha düşük öncelikli bir iş parçacığı beklediğinde gerçekleşir. Gerçek zamanlı (RT) uygulamalarda öncelik ters çevirme sorunu vardır:

Şekil 3. Gerçek zamanlı uygulamalarda öncelik ters çevirme

Linux Tamamen Adil Planlayıcı (CFS) planlama kullanılırken, diğer iş parçacıklarının önceliği daha yüksek olsa bile bir iş parçacığının her zaman çalışma şansı vardır. Sonuç olarak, CFS planlamasına sahip uygulamalar öncelik tersine çevirmeyi bir sorun olarak değil, beklenen davranış olarak ele alır. Bununla birlikte, Android çerçevesinin yüksek öncelikli mesaj dizilerinin ayrıcalığını garanti etmek için RT planlamasına ihtiyaç duyduğu durumlarda önceliğin ters çevrilmesi sorunu çözülmelidir.

Bir bağlayıcı işlemi sırasında öncelik ters çevirme örneği (RT iş parçacığı, bir bağlayıcı iş parçacığının hizmet vermesini beklerken diğer CFS iş parçacığı tarafından mantıksal olarak engellenir):

Şekil 4. Öncelik ters çevirme, gerçek zamanlı mesaj dizilerinin engellenmesi.

Engellemeleri önlemek için, bir RT istemcisinin isteğini işlediğinde Binder iş parçacığının önceliğini geçici olarak bir RT iş parçacığına yükseltmek üzere öncelik devralınmasını kullanabilirsiniz. RT planlamasının sınırlı kaynakları olduğunu ve dikkatli kullanılmasını gerektiğini unutmayın. n CPU'ya sahip bir sistemde, mevcut RT ileti dizisi sayısı da n'dür. Tüm CPU'lar diğer RT ileti dizileri tarafından kullanılıyorsa ek RT ileti dizilerinin beklemesi (ve dolayısıyla son tarihlerini kaçırması) gerekebilir.

Olası tüm öncelik tersine çevirmelerini çözmek için hem binder hem de hwbinder için öncelik devralınmasını kullanabilirsiniz. Ancak bağlayıcı sistem genelinde yaygın olarak kullanıldığı için bağlayıcı işlemleri için öncelik devralınmasını etkinleştirmek, sistemi işleyebileceğinden daha fazla RT iş parçacığıyla spam'leyebilir.

Veri akışı testleri çalıştırma

İşleme hızı testi, binder/hwbinder işleme hızına göre çalıştırılır. Aşırı yük binmeyen bir sistemde gecikme balonları nadir görülür ve iterasyon sayısı yeterince yüksek olduğu sürece etkileri ortadan kaldırılabilir.

  • Bağlayıcı aktarım hızı testi system/libhwbinder/vts/performance/Benchmark_binder.cpp'dedir.
  • hwbinder aktarım hızı testi system/libhwbinder/vts/performance/Benchmark.cpp'dedir.

Test sonuçları

Farklı yığın boyutları kullanan işlemler için örnek aktarım hızı testi sonuçları:

Benchmark                      Time          CPU           Iterations
---------------------------------------------------------------------
BM_sendVec_binderize/4         70302 ns      32820 ns      21054
BM_sendVec_binderize/8         69974 ns      32700 ns      21296
BM_sendVec_binderize/16        70079 ns      32750 ns      21365
BM_sendVec_binderize/32        69907 ns      32686 ns      21310
BM_sendVec_binderize/64        70338 ns      32810 ns      21398
BM_sendVec_binderize/128       70012 ns      32768 ns      21377
BM_sendVec_binderize/256       69836 ns      32740 ns      21329
BM_sendVec_binderize/512       69986 ns      32830 ns      21296
BM_sendVec_binderize/1024      69714 ns      32757 ns      21319
BM_sendVec_binderize/2k        75002 ns      34520 ns      20305
BM_sendVec_binderize/4k        81955 ns      39116 ns      17895
BM_sendVec_binderize/8k        95316 ns      45710 ns      15350
BM_sendVec_binderize/16k      112751 ns      54417 ns      12679
BM_sendVec_binderize/32k      146642 ns      71339 ns       9901
BM_sendVec_binderize/64k      214796 ns     104665 ns       6495
  • Zaman, gidiş dönüş gecikmesini gerçek zamanlı olarak gösterir.
  • CPU, CPU'ların test için planlandığı kümülatif süreyi gösterir.
  • İterasyonlar, test işlevinin kaç kez çalıştırıldığını gösterir.

Örneğin, 8 baytlık bir yük için:

BM_sendVec_binderize/8         69974 ns      32700 ns      21296

… bağlayıcının ulaşabileceği maksimum işleme hızı şu şekilde hesaplanır:

8 baytlık yük ile MAKS. aktarım hızı = (8 * 21296)/69974 ~= 2.423 b/ns ~= 2.268 Gb/s

Test seçenekleri

Sonuçları .json biçiminde almak için testi --benchmark_format=json bağımsız değişkeniyle çalıştırın:

libhwbinder_benchmark --benchmark_format=json
{
  "context": {
    "date": "2017-05-17 08:32:47",
    "num_cpus": 4,
    "mhz_per_cpu": 19,
    "cpu_scaling_enabled": true,
    "library_build_type": "release"
  },
  "benchmarks": [
    {
      "name": "BM_sendVec_binderize/4",
      "iterations": 32342,
      "real_time": 47809,
      "cpu_time": 21906,
      "time_unit": "ns"
    },
   .
}

Gecikme testleri çalıştırma

Gecikme testi, istemcinin işlemi başlatmaya başlaması, işleme almak için sunucu işlemine geçmesi ve sonucu alması için geçen süreyi ölçer. Test, öncelik devralmayı desteklemeyen veya senkronizasyon işaretini dikkate almayan bir planlayıcı gibi işlem gecikmesini olumsuz yönde etkileyebilecek bilinen kötü planlayıcı davranışlarını da arar.

  • Bağlayıcı gecikmesi testi frameworks/native/libs/binder/tests/schd-dbg.cpp'tedir.
  • hwbinder gecikmesi testi system/libhwbinder/vts/performance/Latency.cpp'tedir.

Test sonuçları

Sonuçlar (.json biçiminde), ortalama/en iyi/en kötü gecikme ve kaçırılan son tarih sayısıyla ilgili istatistikleri gösterir.

Test seçenekleri

Gecikme testleri aşağıdaki seçenekleri kullanır:

Komut Açıklama
-i value İtiraz sayısını belirtin.
-pair value İşlem çiftlerinin sayısını belirtin.
-deadline_us 2500 Son tarihi ABD doları cinsinden belirtin.
-v Ayrıntılı (hata ayıklama) çıkışı alın.
-trace Son tarih isabeti durumunda izlemeyi durdurun.

Aşağıdaki bölümlerde her bir seçenek ayrıntılı olarak açıklanmış, kullanım açıklanmış ve örnek sonuçlar verilmiştir.

İterasyonları belirtme

Çok sayıda iterasyon ve ayrıntılı çıkış devre dışı bırakılmış örnek:

libhwbinder_latency -i 5000 -pair 3
{
"cfg":{"pair":3,"iterations":5000,"deadline_us":2500},
"P0":{"SYNC":"GOOD","S":9352,"I":10000,"R":0.9352,
  "other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996},
  "fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
},
"P1":{"SYNC":"GOOD","S":9334,"I":10000,"R":0.9334,
  "other_ms":{ "avg":0.19, "wst":2.9 , "bst":0.055, "miss":2, "meetR":0.9996},
  "fifo_ms": { "avg":0.16, "wst":3.1 , "bst":0.066, "miss":1, "meetR":0.9998}
},
"P2":{"SYNC":"GOOD","S":9369,"I":10000,"R":0.9369,
  "other_ms":{ "avg":0.19, "wst":4.8 , "bst":0.055, "miss":6, "meetR":0.9988},
  "fifo_ms": { "avg":0.15, "wst":1.8 , "bst":0.067, "miss":0, "meetR":1}
},
"inheritance": "PASS"
}

Bu test sonuçları şunları gösterir:

"pair":3
Bir istemci ve sunucu çifti oluşturur.
"iterations": 5000
5.000 iterasyon içerir.
"deadline_us":2500
Son tarih 2500us (2,5 ms)'dir.Çoğu işlemin bu değeri karşılaması beklenir.
"I": 10000
Tek bir test iterasyonu iki (2) işlem içerir:
  • Normal önceliğe göre bir işlem (CFS other)
  • Gerçek zamanlı önceliğe göre bir işlem (RT-fifo)
5.000 iterasyon toplam 10.000 işleme eşittir.
"S": 9352
İşlemlerin 9352'si aynı CPU'da senkronize edilir.
"R": 0.9352
İstemci ve sunucunun aynı CPU'da senkronize edilme oranını gösterir.
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
Normal öncelikli bir araya çağıran tarafından gönderilen tüm işlemler için ortalama (avg), en kötü (wst) ve en iyi (bst) durum. Son tarihten miss sonra iki işlem yapıldığından, karşılama oranı (meetR) 0,9996'dır.
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
other_ms'ye benzer ancak rt_fifo önceliğiyle istemci tarafından başlatılan işlemler için. fifo_ms'ün, avg ve wst değerleri daha düşük ve meetR değeri daha yüksek olacak şekilde other_ms'ten daha iyi bir sonuç vermesi olasıdır (fark, arka planda yük olduğunda daha da belirgin olabilir).

Not: Arka plan yükü, gecikme testindeki aktarım hızı sonucunu ve other_ms tuple'ini etkileyebilir. Arka plan yükü RT-fifo'ten daha düşük önceliğe sahip olduğu sürece yalnızca fifo_ms benzer sonuçlar gösterebilir.

Çift değerlerini belirtme

Her istemci işlemi, istemciye özel bir sunucu işlemiyle eşlenir ve her çift, herhangi bir CPU'da bağımsız olarak planlanabilir. Ancak SYNC işareti honor olduğu sürece CPU taşıma işlemi bir işlem sırasında gerçekleşmemelidir.

Sistemin aşırı yüklenmediğinden emin olun. Aşırı yüklenmiş bir sistemde yüksek gecikmenin olması beklenir ancak aşırı yüklenmiş bir sistemle ilgili test sonuçları yararlı bilgiler sağlamaz. Daha yüksek basınçlı bir sistemi test etmek için -pair #cpu-1 (veya dikkatli bir şekilde -pair #cpu) kullanın. -pair n ile n > #cpu kullanarak test yapmak sistemin aşırı yüklenmesine neden olur ve gereksiz bilgiler oluşturur.

Son tarih değerlerini belirtme

Kapsamlı kullanıcı senaryosu testinden (geçerli bir üründe gecikme testi çalıştırılarak) sonra, 2,5 ms'nin son tarih olduğunu belirledik. Daha yüksek gereksinimleri olan yeni uygulamalarda (ör. saniyede 1.000 fotoğraf) bu son tarih değeri değişir.

Ayrıntılı çıkışı belirtme

-v seçeneği kullanıldığında ayrıntılı çıkış gösterilir. Örnek:

libhwbinder_latency -i 1 -v

-------------------------------------------------- service pid: 8674 tid: 8674 cpu: 1 SCHED_OTHER 0
-------------------------------------------------- main pid: 8673 tid: 8673 cpu: 1 -------------------------------------------------- client pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0
-------------------------------------------------- fifo-caller pid: 8677 tid: 8678 cpu: 0 SCHED_FIFO 99 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 ??? 99
-------------------------------------------------- other-caller pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 SCHED_OTHER 0
  • Hizmet mesaj dizisi, SCHED_OTHER önceliğiyle oluşturulur ve pid 8674 ile CPU:1 içinde çalıştırılır.
  • Ardından fifo-caller tarafından ilk işlem başlatılır. Bu işlemi işlemek için hwbinder, sunucunun (pid: 8674 tid: 8676) önceliğini 99'a yükseltir ve geçici bir planlama sınıfıyla (??? olarak yazdırılır) işaretler. Planlayıcı daha sonra sunucu işlemini çalıştırmak için CPU:0'ye yerleştirir ve istemciyle aynı CPU ile senkronize eder.
  • İkinci işlem çağrısının önceliği SCHED_OTHER olmalıdır. Sunucu, önceliğini düşürür ve arayana SCHED_OTHER önceliğiyle hizmet verir.

Hata ayıklama için izlemeyi kullanma

Gecikme sorunlarını gidermek için -trace seçeneğini belirleyebilirsiniz. Kullanıldığında gecikme testi, kötü gecikme algılandığında izleme günlüğü kaydını durdurur. Örnek:

atrace --async_start -b 8000 -c sched idle workq binder_driver sync freq
libhwbinder_latency -deadline_us 50000 -trace -i 50000 -pair 3
deadline triggered: halt ∓ stop trace
log:/sys/kernel/debug/tracing/trace

Aşağıdaki bileşenler gecikmeyi etkileyebilir:

  • Android derleme modu. Eng modu genellikle userdebug modundan daha yavaştır.
  • Framework. Çerçeve hizmeti, bağlayıcıyı yapılandırmak için ioctl'i nasıl kullanır?
  • Bağlayıcı sürücüsü. Sürücü, ayrıntılı kilitleme özelliğini destekliyor mu? Tüm performans iyileştirme yamalarını içeriyor mu?
  • Çekirdek sürümü. Çekirdeğin gerçek zamanlı özelliği ne kadar iyi olursa sonuçlar da o kadar iyi olur.
  • Çekirdek yapılandırması. Çekirdek yapılandırması, DEBUG_PREEMPT ve DEBUG_SPIN_LOCK gibi DEBUG yapılandırmaları içeriyor mu?
  • Çekirdek planlayıcı. Çekirdekte Enerji Tasarruflu Planlayıcı (EAS) veya Çeşitli Çoklu İşleme (HMP) planlayıcı var mı? Hangi çekirdek sürücüleri (cpu-freq sürücüsü, cpu-idle sürücüsü, cpu-hotplug vb.) planlayıcıyı etkiliyor?