परफ़ॉर्मेंस हिंट एपीआई

रिलीज़ किया गया:

Android 12 (एपीआई लेवल 31) - परफ़ॉर्मेंस हिंट एपीआई

Android 13 (एपीआई लेवल 33) - NDK API में परफ़ॉर्मेंस हिंट मैनेजर

(झलक) Android 15 (DP1) - reportActualWorkDuration()

सीपीयू की परफ़ॉर्मेंस से जुड़े संकेत की मदद से, गेम डाइनैमिक सीपीयू परफ़ॉर्मेंस पर असर डाल सकता है वह अपनी ज़रूरत के हिसाब से सही व्यवहार कर सके. ज़्यादातर डिवाइसों पर, Android डाइनैमिक तरीके से अडजस्ट करता है पिछली मांग के आधार पर वर्कलोड के लिए, सीपीयू की क्लॉक स्पीड और कोर टाइप. अगर कोई वर्कलोड ज़्यादा सीपीयू संसाधनों का इस्तेमाल करता है, तो क्लॉक स्पीड बढ़ जाती है और धीरे-धीरे वर्कलोड ज़्यादा बड़े कोर पर चला जाता है. अगर वर्कलोड कम इस्तेमाल करता है कम संसाधन उपलब्ध हैं. इसके बाद, Android संसाधन के बंटवारे को कम कर देता है. ADPF की मदद से, ऐप्लिकेशन या गेम अपनी परफ़ॉर्मेंस और समयसीमा के बारे में ज़्यादा जानकारी भेज सकता है. यह इससे सिस्टम को ज़्यादा तेज़ी से काम करने (परफ़ॉर्मेंस में सुधार करने) और वर्कलोड पूरा हो जाने पर, घड़ियों को तेज़ी से ऐक्सेस करने की सुविधा मिलती है (बिजली के इस्तेमाल की बचत होती है).

क्लॉक स्पीड

जब Android डिवाइस, अपने सीपीयू की क्लॉक स्पीड को डाइनैमिक तौर पर अडजस्ट करते हैं, तो फ़्रीक्वेंसी अपने कोड की परफ़ॉर्मेंस बदलें. ऐसा कोड डिज़ाइन करना जो डाइनैमिक क्लॉक को ठीक करता है सुरक्षित थर्मल बनाए रखने, परफ़ॉर्मेंस को बेहतर बनाने के लिए स्पीड ज़रूरी है और कुशलता से पावर का इस्तेमाल करते हैं. आप सीधे तौर पर सीपीयू फ़्रीक्वेंसी असाइन नहीं कर सकते डालें. इस वजह से, ऐप्लिकेशन ज़्यादा डिवाइसों पर चलने की कोशिश करते हैं सीपीयू की क्लॉक स्पीड का मतलब, बैकग्राउंड थ्रेड में व्यस्त लूप को चलाना है, ताकि वर्कलोड को उनकी मांग बढ़ जाती है. यह एक गलत तरीका है, क्योंकि इससे ऊर्जा बर्बाद होती है और बढ़ती है डिवाइस पर थर्मल लोड, जब ऐप्लिकेशन असल में संसाधन. सीपीयू PerformanceHint एपीआई को इस समस्या को हल करने के लिए डिज़ाइन किया गया है. इन्होंने बदलाव किया है काम के कुल समय और टारगेट के हिसाब से, सिस्टम को काम के कुल समय की जानकारी देना, Android, ऐप्लिकेशन के लिए सीपीयू से जुड़ी ज़रूरतों की खास जानकारी हासिल कर पाएगा और संसाधन भी मुहैया कराते हैं. इससे बिजली की खपत ज़्यादा होती है. इससे परफ़ॉर्मेंस बेहतर होती है इस्तेमाल किए जाने का स्तर तय करें.

मुख्य टाइप

आपका गेम जिन कोर टाइप पर चलता है वे एक और अहम परफ़ॉर्मेंस होते हैं फ़ैक्टर. Android डिवाइस, अक्सर थ्रेड में असाइन किए गए सीपीयू कोर को बदल देते हैं यह डाइनैमिक, हाल ही के वर्कलोड के हिसाब से काम करता है. सीपीयू के लिए कोर असाइन करना और भी आसान है मुश्किल है. इनमें से कुछ डिवाइसों पर, कोर का इस्तेमाल सिर्फ़ कुछ समय के लिए किया जा सकता है. ऐसा करने के लिए, ये डिवाइस ऊर्जा के ज़्यादा टिकाऊ नहीं होने चाहिए राज्य.

आपके गेम को इन वजहों से सीपीयू कोर अफ़िनिटी सेट करने की कोशिश नहीं करनी चाहिए:

  • डिवाइस के मॉडल के हिसाब से, वर्कलोड का सबसे बेहतर टाइप अलग-अलग होता है.
  • बड़े कोर चलाने की क्षमता, SoC और अलग-अलग संगठनों के हिसाब से अलग-अलग होती है हर डिवाइस मॉडल से मिलने वाला थर्मल सलूशन.
  • थर्मल स्टेट पर पर्यावरण पर होने वाले असर की वजह से, कोर की परफ़ॉर्मेंस खराब हो सकती है का विकल्प चुनें. उदाहरण के लिए, मौसम या फ़ोन केस के इस्तेमाल से, डिवाइस के गर्म होने की स्थिति बदल सकती है एक डिवाइस का इस्तेमाल कर रहे हैं.
  • मुख्य चुने गए विकल्प से, ज़्यादा परफ़ॉर्मेंस वाले नए डिवाइसों को शामिल नहीं किया जा सकता और थर्मल क्षमताओं को कम नहीं किया जा सकता. इस वजह से, डिवाइस अक्सर गेम के प्रोसेसर को अनदेखा कर देते हैं अफ़िनिटी ऑडियंस (एक जैसी पसंद वाले दर्शक) चुनें.

Linux शेड्यूलर के डिफ़ॉल्ट व्यवहार का उदाहरण

Linux शेड्यूलर व्यवहार
पहली इमेज. गवर्नर को सीपीयू फ़्रीक्वेंसी को बेहतर या कम करने में ~200 मि॰से॰ का समय लग सकता है. हर वॉट की सबसे अच्छी परफ़ॉर्मेंस देने के लिए ADPF, डाइनैमिक वोल्टेज ऐंड फ़्रीक्वेंसी स्केलिंग सिस्टम (DVFS) के साथ काम करता है

DVFS के इंतज़ार के समय के मुकाबले परफ़ॉर्मेंस हिंट एपीआई का ऐब्सट्रैक्ट

ADPF, DVFS के इंतज़ार के समय से ज़्यादा ऐब्स्ट्रैक्ट होता है
दूसरी इमेज. ADPF को पता है कि आपकी ओर से सबसे सही फ़ैसला कैसे लेना है
  • अगर टास्क को किसी खास सीपीयू पर चलाना ज़रूरी है, तो Performanceहिंट एपीआई को पता चलता है कि अपनी ओर से फ़ैसला लेने में मदद मिलेगी.
  • इसलिए, आपको अफ़िनिटी ऑडियंस (एक जैसी पसंद वाले दर्शक) का इस्तेमाल करने की ज़रूरत नहीं है.
  • अलग-अलग डिवाइसों के साथ कई टोपोलॉजी (कपड़ों के लिए उपयोग किए जाने वाले डिवाइस) दिए जाते हैं; बल और तापीय विशेषताएं हैं ऐप्लिकेशन डेवलपर को दिखाए जाने के लिए बहुत अलग-अलग है.
  • आप जिस बुनियादी सिस्टम को चला रहे हैं उसके बारे में कोई अनुमान नहीं लगाया जा सकता.

समाधान

ADPF PerformanceHintManager देता है क्लास में शामिल करें, ताकि गेम सीपीयू की क्लॉक स्पीड के लिए Android को परफ़ॉर्मेंस के संकेत भेज सकें और कोर टाइप. इसके बाद, ओएस यह तय कर सकता है कि SoC और डिवाइस का थर्मल सलूशन. अगर आपका ऐप्लिकेशन थर्मल के साथ इस एपीआई का इस्तेमाल करता है की निगरानी कर रहे हैं, तो यह ओएस का इस्तेमाल करने के बजाय, उसे सही संकेत दे सकता है व्यस्त लूप और कोडिंग की दूसरी तकनीकें, जिससे थ्रॉटलिंग हो सकती है.

गेम में, परफ़ॉर्मेंस से जुड़े संकेत इस तरह इस्तेमाल किए जाते हैं:

  1. मिलता-जुलता व्यवहार करने वाले मुख्य थ्रेड के लिए, हिंट सेशन बनाएं. जैसे:
  2. गेम को यह काम कम से कम 2 मि॰से॰ से पहले और चार मि॰से॰ से ज़्यादा समय तक करना चाहिए इससे पहले कि किसी सेशन में सिस्टम के संसाधनों की संख्या बढ़ जाए.
  3. हर संकेत वाले सेशन में, हर सेशन को चलाने के लिए ज़रूरी अवधि का अनुमान लगाएं. सामान्य अवधि, फ़्रेम इंटरवल के बराबर होती है, लेकिन ऐप्लिकेशन कम अवधि के इंटरवल का इस्तेमाल करें, अगर अलग-अलग फ़्रेम के बीच वर्कलोड में ज़्यादा अंतर न हो.

इस सिद्धांत को लागू करने का तरीका यहां बताया गया है:

परफ़ॉर्मेंस हिंट मैनेजर को शुरू करें और createhintsession

सिस्टम सेवा का इस्तेमाल करके मैनेजर पाएं और अपने थ्रेड के लिए हिंट सेशन बनाएं या थ्रेड ग्रुप, एक ही वर्कलोड पर काम कर रहे हों.

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);

अगर ज़रूरी हो, तो थ्रेड सेट करें

रिलीज़ किया गया:

Android 11 (एपीआई लेवल 34)

setThreads का इस्तेमाल करें अन्य थ्रेड होने पर, PerformanceHintManager.Session का फ़ंक्शन जिन्हें बाद में जोड़ा जाना चाहिए. उदाहरण के लिए, अगर आपने फ़िज़िक्स पर आधारित थ्रेड बनाया और इसे सेशन में जोड़ना है, तो इस setThreads एपीआई का इस्तेमाल करें.

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);

अगर एपीआई लेवल कम को टारगेट किया जा रहा है, तो आपको सेशन खत्म करना होगा और जब भी थ्रेड आईडी बदलने की ज़रूरत हो, तो नया सेशन फिर से बनाएं.

काम के कुल समय की जानकारी दें

काम को नैनोसेकंड में पूरा करने में लगने वाला समय ट्रैक करें और रिपोर्ट बनाएं उसे हर चक्र में काम पूरा होने पर सिस्टम पर लागू कर दिया जाएगा. उदाहरण के लिए, अगर अगर यह आपके रेंडरिंग थ्रेड के लिए है, तो इसे हर फ़्रेम पर कॉल करें.

भरोसेमंद तरीके से समय की जानकारी पाने के लिए, इनका इस्तेमाल करें:

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();

उदाहरण के लिए:

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);

ज़रूरत पड़ने पर, काम के लिए तय किया गया कुल समय अपडेट करें

जब भी आपके काम की अवधि में बदलाव होगा, उदाहरण के लिए अगर खिलाड़ी अलग-अलग टारगेट FPS (फ़्रेम प्रति सेकंड) पर सेट करें, updateTargetWorkDuration पर कॉल करें का तरीका बताया जाएगा, ताकि ओएस संसाधनों को उसके हिसाब से अडजस्ट कर सके नए टारगेट के हिसाब से. आपको इसे हर फ़्रेम पर कॉल करने की ज़रूरत नहीं है और सिर्फ़ आपको इसे तब कॉल किया जाता है, जब टारगेट की अवधि बदल जाती है.

C++

APerformanceHint_updateTargetWorkDuration(hint_session, target_duration);

Java

hintSession.updateTargetWorkDuration(targetDuration);