本文說明 Android 音訊系統如何避免 優先順序反轉 並重點介紹可用的技巧
這些技術可能對高效能的開發人員有幫助 音訊應用程式、原始設備製造商 (OEM) 和正在導入音訊的 SoC 供應商 HAL。請注意,使用這些技術 保證能避免資料出現故障或其他故障 用於音訊情境以外的其他用途 實際結果可能會有差異,因此您應自行評估 評估和測試
背景
Android AudioFlinger 音訊伺服器和 AudioTrack/AudioRecord 為縮短延遲時間,我們正在重新建構用戶端導入作業。 這項研究是從 Android 4.1 開始,並持續進行改善 4.2、4.3、4.4 和 5.0。
為了縮短延遲時間,整個系統必須進行多項變更。一 將 CPU 資源指派給具有時效性的關鍵 產生更可預測的排程政策的執行緒。可靠的排程 可在靜止不動時,減少音訊緩衝區的大小和數量 避免效能不足或超支
優先順序反轉
優先順序反轉 是即時系統的故障模式 高優先順序工作在無限制的時間內遭到封鎖 以便讓低優先順序工作釋出資源,例如 受保護的州級資訊) Mutex。
在音訊系統中,優先順序反轉通常會以 故障 (點擊、彈出、丟棄)、 重複音訊 循環緩衝區時 或延遲回應指令時
優先順序反轉的常見解決方法,是增加音訊緩衝區大小。 不過,這個方法會增加延遲時間,而且只會隱藏問題。 而不是解決問題建議您先瞭解和避免優先考慮優先順序 如下圖所示
在 Android 音訊實作中,優先順序反轉的情形 問題通常出現在這些地方因此你應該將注意力集中在此處:
- AudioFlinger 的一般混音器執行緒和快速混音器執行緒之間的差異
- 加快 AudioTrack 的運作速度。 快速混合器執行緒 (兩者的優先順序較高,但稍有不同) 不同的優先順序)
- 達到快速的 AudioRecord 和 快速擷取執行緒 (與上一個類似)
- 導入音訊硬體抽象層 (HAL) 實作程序,例如取消電話或回音取消
- 核心音訊驅動程式中的介面
- 音訊追蹤或 AudioRecord 回呼執行緒與其他應用程式執行緒 (無法由我們控制)
常見解決方案
一般解決方案包括:
- 停用中斷
- 優先順序繼承互斥鎖
在 Linux 使用者空間中,無法停用中斷功能,而且 不適用於對稱多處理器 (SMP)。
優先順序繼承 futexes (快速的使用者空間互斥鎖) 相對較重,因此不會用於音訊系統。 並仰賴信任的用戶端
Android 使用的技巧
實驗一開始為「嘗試鎖定」並設為逾時這些 Mutex Lock 的非阻斷式和受限的封鎖變化版本 作業。鎖定和鎖定時仍可正常運作,但用意是 通常很明顯的故障模式可處理: 如果 用戶端處於忙碌狀態,累計逾時時間 如果長時間不相關的鎖定 逾時。
我們也會使用 不可分割的運算 例如:
- 增加
- 位元「or」
- 位元「and」
這些函式都會傳回先前值,並加入必要的 SMP 技術障礙缺點是可以需要無限次數的重試。 實務上,我們發現重試不是問題。
注意:原子運算及其與記憶體屏障之間的互動 因為無意間誤解及用錯。我們納入了這些方法 這篇文章有完整內容,但建議您也閱讀 Android SMP 入門課程 。
我們仍有並使用了大部分的上述工具,最近 新增了以下技術:
- 使用非封鎖的單一讀取者 FIFO 佇列 。
- 請嘗試 複製 而非 分享 介於 低優先順序模組
- 在需要共用狀態時,請將狀態限制為 最大尺寸 字詞 能以不可分割的形式在單一匯流排作業中存取 不必重試
- 如果是複雜的多字詞狀態,請使用狀態佇列。狀態佇列 基本上是非阻斷單一讀取器的單一寫入者 FIFO 用於狀態而非資料的佇列,但寫入者會收合 彼此相鄰的項目會推動一次推送。
- 請留意 記憶體障礙 以便確認 SMP 的正確性。
- 信任,但進行驗證。 分享時 州/省 程序 我們會假設狀態格式正確。舉例來說 在界限內。執行緒之間不需要進行這項驗證 在同一程序中,相互信任程序之間 通常都具有相同的 UID)。這類資訊也不需要共用 資料 例如 PCM 音訊發生毀損的情形。
非封鎖演算法
非阻塞演算法 是近期研究的科目 但只有單一讀取者 FIFO 佇列例外 但我們發現它們相當複雜且容易出錯
從 Android 4.2 開始,有一項非封鎖規則 單一讀取者/寫入者類別:
- 架構/av/include/media/nbaio/
- 架構/av/media/libnbaio/
- 架構/av/services/audioflinger/StateQueue*
這些設計是針對 AudioFlinger 設計的,並非 一般用途尤其是會妨礙閱讀 難以偵錯您可以將此程式碼視為模型。但 可能會有錯誤且類別不保證一定 其他用途
針對開發人員,部分 OpenSL ES 應用程式程式碼範例應更新為 使用非阻塞演算法,或參照非 Android 的開放原始碼程式庫。
我們已發布一個專為 FIFO 實作的範例
應用方式。查看位於平台來源目錄中的檔案
frameworks/av/audio_utils
:
工具
據我們所知,
找出優先反轉順序,特別是在事件發生前。只有部分通知
研究靜態程式碼分析工具能找出優先要務
若能存取整個程式碼集,則反轉。當然,如果
涉及任何使用者程式碼 (就像在本應用程式使用)
或是大型程式碼集 (例如 Linux 核心和裝置驅動程式)
靜態分析可能不切實際最重要的是
仔細閱讀程式碼,並
系統和互動情形例如
Systrace
和
ps -t -p
有助於在發生優先順序反轉後才查看
且不會事先告知您
最後一個字詞
完成上述討論後,別害怕互斥鎖。互斥鎖 正確使用和執行時,是您日常使用上的好幫手 執行一般非重要用途但介於 低優先順序工作和有時效性的系統互斥鎖 問題