Performans İpucu API'sı

Yayınlanma tarihi:

Android 12 (API Düzeyi 31) - Performance ipucu API

Android 13 (API Düzeyi 33) - NDK API'de Performans İpucu Yöneticisi

(Önizleme) Android 15 (DP1) - reportActualWorkDuration()

CPU performansı ipuçlarıyla bir oyun dinamik CPU performansını etkileyebilir daha iyi karşılaması gerekir. Android, çoğu cihazda önceki taleplere göre iş yükü için CPU saat hızı ve çekirdek türü. Bir iş yükü daha fazla CPU kaynağı kullanıyorsa saat hızı yükselir ve zamanla daha büyük bir çekirdeğe taşınır. İş yükünde daha az kaynak Android, kaynak ayırmayı azaltır. ADPF'de uygulama, performansı ve son tarihleri hakkında ek bir sinyal gönderebilir. Bu sistemin daha agresif bir şekilde gelişmesine (performansın iyileşmesine) ve iş yükü tamamlandığında hızlı bir şekilde çalışır (güç kullanımından tasarruf).

Saat hızı

Android cihazlar CPU saat hızını dinamik olarak ayarladığında frekansı da kodunuzun performansını değiştirin. Dinamik saate yönelik kod tasarlama hız, performansı en üst düzeye çıkarmak açısından önemlidir. ve gücü verimli bir şekilde kullanmanız gerekir. CPU frekanslarını doğrudan atayamazsınız girin. Dolayısıyla, uygulamaların daha yüksek bir hızda çalışmaya çalıştığı yaygın bir yöntem CPU saat hızları, iş yükünün azaltılması için arka plan iş parçacığında daha talepkar gibi görünüyor. Bu kötü bir uygulamadır çünkü güç israfına yol açar ve ancak uygulama, ekstra enerjiyi kullanmadığında cihazdaki termal yük kaynaklar. CPU PerformanceHint API, bu sorunu gidermek için tasarlanmıştır. Ölçüt gerçek çalışma süresini ve hedef çalışma süresini sisteme bildirmek, Android, uygulamanın CPU ihtiyaçları hakkında genel bir bakış elde edebilir ve uygulamayı dağıtabilir. ve kaynakların verimli bir şekilde kullanılmasını sağlar. Bu, verimli güçte optimum performans sağlar tüketiyoruz.

Çekirdek türleri

Oyununuzun üzerinde çalıştığı CPU çekirdeği türleri de bir diğer önemli performanstır. faktörünü içerir. Android cihazlar genellikle bir iş parçacığına atanan CPU çekirdeğini değiştirir performansa göre dinamik olarak belirleyebilirsiniz. CPU çekirdek ataması birden fazla çekirdek türüne sahip SoC'lerde karmaşıktır. Bu cihazların bazılarında çekirdekler, termal açıdan sürdürülebilir olmayan bir ortama durumu.

Oyununuz aşağıdaki nedenlerden dolayı CPU çekirdeği yakınlığını ayarlamaya çalışmamalıdır:

  • İş yükü için en iyi çekirdek türü, cihaz modeline göre değişir.
  • Daha büyük çekirdekleri çalıştırmanın sürdürülebilirliği, SoC'ye ve kullandığınız çeşitli her cihaz modelinin sağladığı termal çözümler.
  • Termal durum üzerindeki çevresel etki, çekirdekleri daha da karmaşıklaştırabilir. seçim. Örneğin, hava durumu veya telefon kılıfı termal durumu değiştirebilir bir şekilde tanımlar.
  • Temel seçim, ek performansa sahip ve ek performansa sahip yeni cihazları barındıramaz. ısısal kapasitedir. Sonuç olarak, cihazlar genellikle bir oyunun işlemcisini yoksayar benzetimidir.

Varsayılan Linux zamanlayıcı davranışı örneği

Linux Planlayıcısı Davranışı
Şekil 1. Valinin CPU frekansını artırması veya azaltması yaklaşık 200 ms sürebilir. ADPF, vat başına en iyi performansı sağlamak için Dinamik Voltaj ve Frekans Ölçeklendirme sistemiyle (DVFS) birlikte çalışır
'nı inceleyin.

PerformanceHint API, DVFS gecikmelerinden daha fazlasını özetliyor

ADPF Soyutları DVFS Gecikmelerinden daha fazla
Şekil 2. ADPF sizin adınıza en iyi kararı nasıl vereceğini bilir
'nı inceleyin.
  • Görevlerin belirli bir CPU'da çalışması gerekiyorsa PerformanceHint API sizin adınıza vermeniz gerekir.
  • Bu nedenle, yakın ilgi alanı özelliğini kullanmanız gerekmez.
  • Cihazlar çeşitli topolojilere sahiptir: Güç ve termal özellikler: uygulama geliştiricilere gösterilemeyecek kadar çeşitlidir.
  • Çalıştığınız temel sistem hakkında varsayımlarda bulunamazsınız.

Çözüm

ADPF, PerformanceHintManager sağlar oyunların CPU saat hızı ve performans için Android'e performans ipuçları gönderebilmesi çekirdek türü. Daha sonra işletim sistemi, Çip üzerinde sistem (SoC) ve cihazın termal çözümü. Uygulamanız, thermal ile birlikte bu API'yi kullanıyorsa Bu, durum izleme özelliğini kullanmak yerine işletim sistemine daha bilinçli ipuçları sağlayabilir. yoğun döngüleri ve kısıtlamaya neden olabilecek diğer kodlama tekniklerini kullanabilirsiniz.

Performans ipuçları oyunda şu şekilde kullanılır:

  1. Benzer şekilde davranan önemli ileti dizileri için ipucu oturumları oluşturun. Örnek:
  2. Oyun bunu erkenden, en az 2 ms. ve tercihen 4 ms.den yüksek bir sürede yapmalıdır. daha yüksek sistem kaynaklarına ihtiyaç duymadan önce
  3. Her ipucu oturumunda, her oturumun çalışması için gereken süreyi tahmin edin. Tipik süre bir kare aralığına eşdeğerdir ancak uygulama iş yükü kareler arasında önemli ölçüde farklılık göstermiyorsa daha kısa aralık.

Bu teoriyi pratiğe dökmek için:

PerformanceHintManager'ı başlatın ve createHintSession'ı başlatın

Sistem hizmetini kullanarak yöneticiyi alın ve iş parçacığınız için bir ipucu oturumu oluşturun veya iş parçacığı grubunun aynı iş yükü üzerinde çalışması gerekir.

C++

int32_t tids[1];
tids[0] = gettid();
int64_t target_fps_nanos = getFpsNanos();
APerformanceHintManager* hint_manager = APerformanceHint_getManager();
APerformanceHintSession* hint_session =
  APerformanceHint_createSession(hint_manager, tids, 1, target_fps_nanos);

Java

int[] tids = {
  android.os.Process.myTid()
};
long targetFpsNanos = getFpsNanos();
PerformanceHintManager performanceHintManager =
  (PerformanceHintManager) this.getSystemService(Context.PERFORMANCE_HINT_SERVICE);
PerformanceHintManager.Session hintSession =
  performanceHintManager.createHintSession(tids, targetFpsNanos);

Gerekirse mesaj dizilerini ayarlayın

Yayınlanma tarihi:

Android 11 (API Düzeyi 34)

setThreads'ı kullanma başka iş parçacıklarınız olduğunda PerformanceHintManager.Session işlevi bunların daha sonra eklenmesi gerekir. Örneğin, fiziki dersinizi oluşturup daha sonra oturuma eklemeniz gerekirse bu setThreads API'yi kullanabilirsiniz.

C++

auto tids = thread_ids.data();
std::size_t size = thread_ids_.size();
APerformanceHint_setThreads(hint_session, tids, size);

Java

int[] tids = new int[3];

// add all your thread IDs. Remember to use android.os.Process.myTid() as that
// is the linux native thread-id.
// Thread.currentThread().getId() will not work because it is jvm's thread-id.
hintSession.setThreads(tids);

Daha düşük API Düzeylerini hedefliyorsanız oturumu kaldırmanız ve İleti dizisi kimliklerini değiştirmeniz gerektiğinde yeni bir oturum yeniden oluşturun.

Gerçek Çalışma Süresini Raporla

İşi nanosaniyeler ve rapor halinde tamamlamak için gereken gerçek süreyi takip edin tamamlanmasından sonra da sisteme aktarır. Örneğin, bu, oluşturma iş parçacıklarınız içindir. Her karede bunu çağırın.

Zamanın güvenilir bir şekilde hesaplanması için şunları kullanın:

C++

clock_gettime(CLOCK_MONOTONIC, &clock); // if you prefer "C" way from <time.h>
// or
std::chrono::high_resolution_clock::now(); // if you prefer "C++" way from <chrono>

Java

System.nanoTime();

Örnek:

C++

// All timings should be from `std::chrono::steady_clock` or `clock_gettime(CLOCK_MONOTONIC, ...)`
auto start_time = std::chrono::high_resolution_clock::now();

// do work

auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count();
int64_t actual_duration = static_cast<int64_t>(duration);

APerformanceHint_reportActualWorkDuration(hint_session, actual_duration);

Java

long startTime = System.nanoTime();

// do work

long endTime = System.nanoTime();
long duration = endTime - startTime;

hintSession.reportActualWorkDuration(duration);

Gerektiğinde Hedef Çalışma Süresini güncelleme

Hedef çalışma süreniz değiştiğinde, örneğin, oyuncu bir farklı bir hedef fps'ye sahipse updateTargetWorkDuration işletim sisteminin kaynakları uygun şekilde ayarlayabilmesi için sisteme . Her karede çağırmanız gerekmez. hedef süre değiştiğinde bu parametreyi çağırın.

C++

APerformanceHint_updateTargetWorkDuration(hint_session, target_duration);

Java

hintSession.updateTargetWorkDuration(targetDuration);