रिलीज़ किया गया:
Android 12 (एपीआई लेवल 31) - परफ़ॉर्मेंस हिंट एपीआई
Android 13 (एपीआई लेवल 33) - NDK API में परफ़ॉर्मेंस हिंट मैनेजर
(झलक) Android 15 (DP1) - reportActualWorkDuration()
सीपीयू की परफ़ॉर्मेंस से जुड़े संकेत की मदद से, गेम डाइनैमिक सीपीयू परफ़ॉर्मेंस पर असर डाल सकता है वह अपनी ज़रूरत के हिसाब से सही व्यवहार कर सके. ज़्यादातर डिवाइसों पर, Android डाइनैमिक तरीके से अडजस्ट करता है पिछली मांग के आधार पर वर्कलोड के लिए, सीपीयू की क्लॉक स्पीड और कोर टाइप. अगर कोई वर्कलोड ज़्यादा सीपीयू संसाधनों का इस्तेमाल करता है, तो क्लॉक स्पीड बढ़ जाती है और धीरे-धीरे वर्कलोड ज़्यादा बड़े कोर पर चला जाता है. अगर वर्कलोड कम इस्तेमाल करता है कम संसाधन उपलब्ध हैं. इसके बाद, Android संसाधन के बंटवारे को कम कर देता है. ADPF की मदद से, ऐप्लिकेशन या गेम अपनी परफ़ॉर्मेंस और समयसीमा के बारे में ज़्यादा जानकारी भेज सकता है. यह इससे सिस्टम को ज़्यादा तेज़ी से काम करने (परफ़ॉर्मेंस में सुधार करने) और वर्कलोड पूरा हो जाने पर, घड़ियों को तेज़ी से ऐक्सेस करने की सुविधा मिलती है (बिजली के इस्तेमाल की बचत होती है).
क्लॉक स्पीड
जब Android डिवाइस, अपने सीपीयू की क्लॉक स्पीड को डाइनैमिक तौर पर अडजस्ट करते हैं, तो फ़्रीक्वेंसी
अपने कोड की परफ़ॉर्मेंस बदलें. ऐसा कोड डिज़ाइन करना जो डाइनैमिक क्लॉक को ठीक करता है
सुरक्षित थर्मल बनाए रखने, परफ़ॉर्मेंस को बेहतर बनाने के लिए स्पीड ज़रूरी है
और कुशलता से पावर का इस्तेमाल करते हैं. आप सीधे तौर पर सीपीयू फ़्रीक्वेंसी असाइन नहीं कर सकते
डालें. इस वजह से, ऐप्लिकेशन ज़्यादा डिवाइसों पर चलने की कोशिश करते हैं
सीपीयू की क्लॉक स्पीड का मतलब, बैकग्राउंड थ्रेड में व्यस्त लूप को चलाना है, ताकि वर्कलोड को
उनकी मांग बढ़ जाती है. यह एक गलत तरीका है, क्योंकि इससे ऊर्जा बर्बाद होती है और बढ़ती है
डिवाइस पर थर्मल लोड, जब ऐप्लिकेशन असल में
संसाधन. सीपीयू PerformanceHint
एपीआई को इस समस्या को हल करने के लिए डिज़ाइन किया गया है. इन्होंने बदलाव किया है
काम के कुल समय और टारगेट के हिसाब से, सिस्टम को काम के कुल समय की जानकारी देना,
Android, ऐप्लिकेशन के लिए सीपीयू से जुड़ी ज़रूरतों की खास जानकारी हासिल कर पाएगा और
संसाधन भी मुहैया कराते हैं. इससे बिजली की खपत ज़्यादा होती है. इससे परफ़ॉर्मेंस बेहतर होती है
इस्तेमाल किए जाने का स्तर तय करें.
मुख्य टाइप
आपका गेम जिन कोर टाइप पर चलता है वे एक और अहम परफ़ॉर्मेंस होते हैं फ़ैक्टर. Android डिवाइस, अक्सर थ्रेड में असाइन किए गए सीपीयू कोर को बदल देते हैं यह डाइनैमिक, हाल ही के वर्कलोड के हिसाब से काम करता है. सीपीयू के लिए कोर असाइन करना और भी आसान है मुश्किल है. इनमें से कुछ डिवाइसों पर, कोर का इस्तेमाल सिर्फ़ कुछ समय के लिए किया जा सकता है. ऐसा करने के लिए, ये डिवाइस ऊर्जा के ज़्यादा टिकाऊ नहीं होने चाहिए राज्य.
आपके गेम को इन वजहों से सीपीयू कोर अफ़िनिटी सेट करने की कोशिश नहीं करनी चाहिए:
- डिवाइस के मॉडल के हिसाब से, वर्कलोड का सबसे बेहतर टाइप अलग-अलग होता है.
- बड़े कोर चलाने की क्षमता, SoC और अलग-अलग संगठनों के हिसाब से अलग-अलग होती है हर डिवाइस मॉडल से मिलने वाला थर्मल सलूशन.
- थर्मल स्टेट पर पर्यावरण पर होने वाले असर की वजह से, कोर की परफ़ॉर्मेंस खराब हो सकती है का विकल्प चुनें. उदाहरण के लिए, मौसम या फ़ोन केस के इस्तेमाल से, डिवाइस के गर्म होने की स्थिति बदल सकती है एक डिवाइस का इस्तेमाल कर रहे हैं.
- मुख्य चुने गए विकल्प से, ज़्यादा परफ़ॉर्मेंस वाले नए डिवाइसों को शामिल नहीं किया जा सकता और थर्मल क्षमताओं को कम नहीं किया जा सकता. इस वजह से, डिवाइस अक्सर गेम के प्रोसेसर को अनदेखा कर देते हैं अफ़िनिटी ऑडियंस (एक जैसी पसंद वाले दर्शक) चुनें.
Linux शेड्यूलर के डिफ़ॉल्ट व्यवहार का उदाहरण
![Linux शेड्यूलर व्यवहार](https://developer.android.com/static/games/optimize/adpf/images/adpf_linux_sched_behavior.png?hl=hi)
DVFS के इंतज़ार के समय के मुकाबले परफ़ॉर्मेंस हिंट एपीआई का ऐब्सट्रैक्ट
![ADPF, DVFS के इंतज़ार के समय से ज़्यादा ऐब्स्ट्रैक्ट होता है](https://developer.android.com/static/games/optimize/adpf/images/adpf_dvfs_latency.png?hl=hi)
- अगर टास्क को किसी खास सीपीयू पर चलाना ज़रूरी है, तो Performanceहिंट एपीआई को पता चलता है कि अपनी ओर से फ़ैसला लेने में मदद मिलेगी.
- इसलिए, आपको अफ़िनिटी ऑडियंस (एक जैसी पसंद वाले दर्शक) का इस्तेमाल करने की ज़रूरत नहीं है.
- अलग-अलग डिवाइसों के साथ कई टोपोलॉजी (कपड़ों के लिए उपयोग किए जाने वाले डिवाइस) दिए जाते हैं; बल और तापीय विशेषताएं हैं ऐप्लिकेशन डेवलपर को दिखाए जाने के लिए बहुत अलग-अलग है.
- आप जिस बुनियादी सिस्टम को चला रहे हैं उसके बारे में कोई अनुमान नहीं लगाया जा सकता.
समाधान
ADPF PerformanceHintManager
देता है
क्लास में शामिल करें, ताकि गेम सीपीयू की क्लॉक स्पीड के लिए Android को परफ़ॉर्मेंस के संकेत भेज सकें और
कोर टाइप. इसके बाद, ओएस यह तय कर सकता है कि SoC और
डिवाइस का थर्मल सलूशन. अगर आपका ऐप्लिकेशन थर्मल के साथ इस एपीआई का इस्तेमाल करता है
की निगरानी कर रहे हैं, तो यह ओएस का इस्तेमाल करने के बजाय, उसे सही संकेत दे सकता है
व्यस्त लूप और कोडिंग की दूसरी तकनीकें, जिससे थ्रॉटलिंग हो सकती है.
गेम में, परफ़ॉर्मेंस से जुड़े संकेत इस तरह इस्तेमाल किए जाते हैं:
- मिलता-जुलता व्यवहार करने वाले मुख्य थ्रेड के लिए, हिंट सेशन बनाएं. जैसे:
- रेंडरिंग थ्रेड और उसकी डिपेंडेंसी को एक सेशन मिलता है
- Cocos में, मुख्य इंजन थ्रेड और रेंडर थ्रेड एक हो जाते हैं सेशन
- Unity में, ज़रूरत के हिसाब से परफ़ॉर्मेंस देने वाले Android प्रोवाइडर का प्लगिन इंटिग्रेट करें
- Unreal में, Unreal अडैप्टिव परफ़ॉर्मेंस प्लगिन को इंटिग्रेट करें और एक से ज़्यादा क्वालिटी लेवल के साथ काम करने के लिए बढ़ाने के विकल्प
- IO थ्रेड को एक और सेशन मिलता है
- ऑडियो थ्रेड को तीसरा सेशन शुरू होता है
- रेंडरिंग थ्रेड और उसकी डिपेंडेंसी को एक सेशन मिलता है
- गेम को यह काम कम से कम 2 मि॰से॰ से पहले और चार मि॰से॰ से ज़्यादा समय तक करना चाहिए इससे पहले कि किसी सेशन में सिस्टम के संसाधनों की संख्या बढ़ जाए.
- हर संकेत वाले सेशन में, हर सेशन को चलाने के लिए ज़रूरी अवधि का अनुमान लगाएं. सामान्य अवधि, फ़्रेम इंटरवल के बराबर होती है, लेकिन ऐप्लिकेशन कम अवधि के इंटरवल का इस्तेमाल करें, अगर अलग-अलग फ़्रेम के बीच वर्कलोड में ज़्यादा अंतर न हो.
इस सिद्धांत को लागू करने का तरीका यहां बताया गया है:
परफ़ॉर्मेंस हिंट मैनेजर को शुरू करें और 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);