發布日期:
Android 12 (API 級別 31) - Performance Hint API
Android 13 (API 級別 33) - NDK API 中的效能提示管理工具
(預先發布版) Android 15 (DP1) - reportActualWorkDuration()
透過 CPU 效能提示,遊戲可能會影響動態 CPU 效能 才能更符合自身需求在大多數裝置上,Android 都會以動態方式 依據先前的需求,評估工作負載的 CPU 時脈速度和核心類型。 如果工作負載使用更多 CPU 資源,時鐘速度會增加 則最終會移至更大的核心如果工作負載耗用較少 隨後 Android 會減少資源分配有了 ADPF 或遊戲傳送更多有關效能和期限的信號。這個 協助系統更積極地調高 (提升效能) 並降低 。
時脈速度
當 Android 裝置動態調整 CPU 時脈速度時,
變更程式碼的效能設計處理動態時鐘的程式碼
速度對最佳效能而言至關重要,熱能保持安全溫度
狀態,有效運用電源您無法直接指派 CPU 頻率
。因此,應用程式嘗試以
CPU 時脈速度是在背景執行緒中執行忙碌迴圈,讓工作負載
似乎更要求嚴苛。這種行為會浪費力量,但會浪費電力
當應用程式並非實際使用
再複習一下,機構節點
是所有 Google Cloud Platform 資源的根節點CPU PerformanceHint
API 的設計可解決這個問題。變更者:
告知系統實際工作時間長度和目標工作持續時間。
Android 將能大致瞭解應用程式的 CPU 需求和分配情形
有效率地管理資源如此才能實現最佳效能,實現有效率的高效電力
提高用量上限
核心類型
執行遊戲的 CPU 核心類型是另一項重要效能 。Android 裝置通常會變更指派給執行緒的 CPU 核心 依據最近的工作負載行為動態調度資源CPU 核心指派作業 含有多種核心類型的 SoC在某些裝置上 核心應短暫使用,且在缺乏熱能性的情況下 時間。
您的遊戲不應嘗試設定 CPU 核心相依性,原因如下:
- 工作負載的最佳核心類型會因裝置型號而異。
- 執行大型核心的永續發展機制因 SoC 和 以及個別裝置型號提供的熱解解決方案
- 環境對熱力狀態的影響可能會使核心更加複雜 就是用哪一種烤箱或刀子都可以 那麼預先建構的容器或許是最佳選擇舉例來說,天氣或手機保護殼可能會改變熱力狀態 裝置本身的狀態
- 核心選擇無法因應效能更高的新裝置, 以及熱力功能因此,裝置通常會忽略遊戲的處理器 興趣相似。
預設 Linux 排程器行為範例
![Linux 排程器行為](https://developer.android.com/static/games/optimize/adpf/images/adpf_linux_sched_behavior.png?authuser=0000&hl=zh-tw)
PerformanceHint API 的抽象化機制比 DVFS 延遲時間長
![ADPF 的摘要比 DVFS 延遲時間長](https://developer.android.com/static/games/optimize/adpf/images/adpf_dvfs_latency.png?authuser=0000&hl=zh-tw)
- 如果工作需要在特定 CPU 上執行,PerformanceHint API 知道如何 代您做出決定
- 因此,您不需要使用相依性。
- 裝置各有不同的拓撲;功率與熱力包括 因此缺乏多樣性, 導致應用程式開發人員的知名度差不多
- 請勿就執行的基礎系統做出任何假設。
解決方案
ADPF 則提供 PerformanceHintManager
類別,讓遊戲能向 Android 傳送效能提示給 Android 以瞭解 CPU 時脈速度
核心類型這樣一來,OS 就可以根據 SoC 和
裝置的熱解解決方案如果應用程式使用這個 API 搭配熱能
因此可以為 OS 提供更多相關資訊
可能引發節流的繁忙迴圈和其他程式設計技術。
以下說明遊戲使用效能提示的方式:
- 為行為相似的主要執行緒建立提示工作階段。例如:
- 轉譯執行緒及其依附元件會取得一個工作階段
- 在 Cocos 中,主要引擎執行緒和轉譯執行緒會獲得一個 工作階段
- 在 Unity 中,整合自動調整效能 Android 供應商外掛程式
- 在 Unreal 中,整合 Unreal Adaptive Performance 外掛程式並使用 支援多個品質等級的擴充性選項
- 為 IO 執行緒取得另一個工作階段
- 為音訊執行緒取得第三個工作階段
- 轉譯執行緒及其依附元件會取得一個工作階段
- 遊戲應盡早執行這項作業 (建議至少 2 毫秒,最好超過 4 毫秒) 就必須增加系統資源
- 在每個提示工作階段中,預測各工作階段所需的執行時間。 一般來說,時間長度相當於影格間隔,但應用程式可以使用 較短的間隔。
以下說明如何實際應用理論:
初始化 PerformanceHintManager 和 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 (API 級別 34)
使用 setThreads
在其他執行緒時,PerformanceHintManager.Session
函式
供稍後新增舉例來說,如果建立物理執行緒
然後需要將其新增至工作階段,您可以使用這個 setThreads
API。
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);
如要指定較低的 API 級別,則需刪除工作階段 每次需要變更執行緒 ID 時,再重新建立新的工作階段。
回報實際工作時間長度
以奈秒為單位追蹤完成工作所需的實際時間長度,並產生報表 每個週期完成工作後 系統就會將其送回系統中舉例來說 這要用於轉譯執行緒,請在每個影格上呼叫這個程式碼。
如要穩定取得實際時間,請使用:
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);
視需要更新目標工作時間長度
每當目標工作持續時間改變時,例如玩家選擇
不同的目標每秒影格數,請呼叫 updateTargetWorkDuration
方法,讓系統知道 OS 才能根據
複製到新的目標您不必在每個影格都呼叫這個程式碼,只需
在目標時間長度變更時呼叫此函式。
C++
APerformanceHint_updateTargetWorkDuration(hint_session, target_duration);
Java
hintSession.updateTargetWorkDuration(targetDuration);