背景面試
寫這篇文章,主要是爲了之後面試方便。由於我簡歷上寫了,上一份工做的最大亮點是將人臉解鎖的速度由1200ms優化到了600ms,因此這些內容已經回答無數遍了。但每次總以爲回答的不完整,或者說總感受能夠發揮得更好,因而這裏作一些簡單的總結性的記錄。算法
我2018年4月份進入到某手機公司,在其中工做了兩年多的時間,這期間主要負責人臉解鎖的功能。人臉解鎖的速度優化,是入職開始的一個很重要的任務,前先後後持續了很長時間。作優化前,首先是明確目標,我接手時人臉解鎖的速度是1200ms左右,而咱們是參照的精品機Oppo、vivo、小米、華爲等主流機型解鎖速度大約在400~700ms不等,因此這也就成了我優化的目標。架構
整我的臉解鎖的架構圖以下所示:性能
優化的基本手段是將整個啓動過程拆分爲多個階段,而後針對每個階段進行優化,優化流程邏輯或者採用更高效技術,概括起來主要有以下這些步驟:測試
一、從按power鍵到SystemUI中的KeyguardService優化
優化前,使用的是廣播方式,但咱們知道使用廣播方式來實現IPC性能是很是差的,速度很慢。優化後,採用AIDL取代廣播方式,提高40ms左右。線程
有些面試官會問:爲何使用AIDL比使用廣播速度更快?設計
網上沒有搜到比較權威的答案,我本身整理了一下,我我的認爲有以下幾個緣由:(1)廣播的發送和接收過程當中,有屢次Binder實現的IPC。廣播實現跨進程通訊的方式也經過Binder實現的,這一點和AIDL同樣。可是廣播在註冊時會將IntentFilter和Receiver信息經過Binder方式註冊到AMS中,這裏面會有不少封裝、過濾等操做,將action,Receiver,Context、IntentFilter進行關聯。發送者發送消息時會將action等信息封裝到Intent中,而後經過Binder方式與AMS通訊,將Intent等信息傳入AMS中。AMS中通過匹配action,找到對應的註冊者和接收者,而後再經過Binder方式和Receiver通訊,這樣就完成了一次廣播的發送和接收,其中發生了屢次Binder。而AIDL方式就過程就簡單不少,直接在發送者和接收者之間一次Binder便可。廣播是四大組件之一,在使用過程當中會存在不少中間的處理過程,好比對Intent等的中間處理等。(2)廣播有前臺廣播和後臺廣播之分,默認是後臺廣播。系統的內部存在無數的廣播,因爲系統資源有限,會優先處理一些很是重要的廣播,這就使得默認狀況下的廣播會低優先級處理這些後臺廣播。一樣也因爲系統資源有限,因此不能隨意將廣播設置爲前臺廣播。(3)根據註冊的方式不一樣,廣播有靜態註冊和動態註冊的區分,若是是靜態註冊,就是並行廣播,若是有多個地方註冊了該廣播,會根據註冊的時間來依次處理廣播事件。這一點不一樣於串行廣播,動態註冊是串行廣播。調試
二、SystemUI與FaceId Service長期保持鏈接。blog
SystemUI與FaceId是經過AIDL來通訊的, 優化前,SytemUI每次和FaceId通訊完畢後都會斷開鏈接,這樣就致使在下次使用人臉解鎖時,必須從新創建鏈接,會有必定程度的延遲。優化的方法就是讓SystemUI和FaceId保持長久的鏈接。固然這一點縮短的時間並不太多。
三、使用Camera2 API代替Camera1 API
系統提供了Camera API-2,是官方對API-1的優化,性能更穩定,使用起來也更加方便。官方並無明確說明使用API-2會比API-1更加快速,但實際開發中發現,使用API-2替換後,整個開啓預覽和開啓相機的過程縮短了150ms左右。
四、提升相機幀率,儘可能減小人臉解鎖算法的等待時間
人臉解鎖的核心流程是:SDK會預先錄入使用者的人臉數據,在須要解鎖時,相機經過攝像頭以必定的幀率獲取圖像信息,經過API中的回調將圖像信息傳遞給SDK。SDK中封裝了人臉匹配算法,該算法會將相機傳遞的圖像信息和預存的人臉數據進行匹配,並根據匹配結果返回對應的值,好比環境太黑、檢測不到人臉、和預存的不是同一我的、匹配成功等各類匹配結果,都有一個數字與之對應。
SDK在匹配時,若是成功,一次匹配的時間大約是30ms,若是是失敗的匹配,一次匹配大約50ms~100ms不等(在匹配過程當中,若是有新的圖像數據傳遞過來,會被過濾掉)。而日常使用時經常不能一次匹配成功,本次匹配失敗後,很快從相機拿下一筆圖像來匹配,直到在指定時間(設置的是5s)內匹配成功。爲了可以讓本次匹配失敗後很快拿到下一筆圖像,這就要求相機提升獲取圖像的幀率。這一點督促相機團隊的同事,修改相機參數,綜合考慮之下,取了15ms每幀的頻率。
五、合理設置相機的初始曝光值
相機通常會默認設置一個曝光值,在不一樣環境中使用時,再根據周圍環境來調整,以適應周圍的光照環境。若是默認的曝光值設置不合適,會致使剛開啓相機時,獲得的前幾筆圖像要麼太暗,要麼太亮,須要自我調整達到一個高質量的狀態。
在優化前,因爲對默認的曝光值設置不合理,致使開啓人臉解鎖功能時,即使是很正常的光照環境下,面對正確的人臉時,前面屢次匹配都由於圖像質量太差,致使匹配失敗。每次匹配失敗都會浪費50~100ms的時間,這就致使每次解鎖成功前,都會浪費300ms甚至更多的時間在相機自身調整曝光值上。
在後面作優化時,經過大量的測試和分析log,發現了每次匹配都不能一次成功的問題,而後將相機提供的數據轉爲圖片,才發現圖像的質量問題。後來和相機團隊的同事,共同調試,獲得一個比較合適的初始曝光值,解決了這個問題。
六、在啓動人臉解鎖時啓動CPU拉頻,併合理處理速度和省電之間的關係
人臉解鎖算法執行是一個高密集計算的操做,爲了提升解鎖的速度,優化過程當中採用了調度CPU最大核,並提升CPU頻率的作法,使得匹配的速度有所提升。
調度CPU最大核並提升CPU頻率,是一個很是耗電的過程。爲了更好地平衡匹配速度和省電,這裏又作了一個設計:人臉解鎖超時時間設置的是5s,但實際上,若是周圍環境正常,且是正確的人臉,大部分場景下都能在前1s內解鎖完成,只有在環境異常或者非正確人臉的時候,纔會在1s後還須要匹配,此種場景能解鎖的機率就比較小了。因此這裏的處理方法是,在人臉解鎖的前1s調度CPU最大核,若是尚未解鎖,則將CPU調回正常,而不是一直都使用CPU大核和高頻。
七、合理使用並行代替串行
人臉匹配成功後,就能夠馬上走解鎖流程,並調用相機的關閉方法,而關閉相機須要150ms的時間。優化前原開發者採用的是串行的方式,也就是在人臉匹配完成後,在同一個線程中調用了關閉相機操做,相機關閉後才走鎖屏界面消失的流程。這個優化點應該是很明顯的,關閉相機的操做放在單獨的一個線程去執行就能夠了,這樣一來就可以再優化150ms的時間。至於原開發者爲何要採用串行,不得而知。
固然,優化過程還有其餘不少的細節,好比一些流程的時間複雜度優化,非必要流程的精簡,要求sdk人臉匹配算法作優化,新手機中使用了性能更好的CPU、相機硬件等。