【面試】面試官:說說你上個項目中做得比較好的地方——Android手機鎖屏人臉解鎖優化總結

背景

       寫這篇文章,主要是爲了以後面試方便。因爲我簡歷上寫了,上一份工作的最大亮點是將人臉解鎖的速度由1200ms優化到了600ms,所以這些內容已經回答無數遍了。但每次總覺得回答的不完整,或者說總感覺可以發揮得更好,於是這裏做一些簡單的總結性的記錄。

       我2018年4月份進入到某手機公司,在其中工作了兩年多的時間,這期間主要負責人臉解鎖的功能。人臉解鎖的速度優化,是入職開始的一個很重要的任務,前前後後持續了很長時間。做優化前,首先是明確目標,我接手時人臉解鎖的速度是1200ms左右,而我們是參照的精品機Oppo、vivo、小米、華爲等主流機型解鎖速度大約在400~700ms不等,所以這也就成了我優化的目標。

       整個人臉解鎖的架構圖如下所示:

 

     優化的基本手段是將整個啓動過程拆分爲多個階段,然後針對每一個階段進行優化,優化流程邏輯或者採用更高效技術,歸納起來主要有如下這些步驟:

 

1、從按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)根據註冊的方式不同,廣播有靜態註冊和動態註冊的區分,如果是靜態註冊,就是並行廣播,如果有多個地方註冊了該廣播,會根據註冊的時間來依次處理廣播事件。這一點不同於串行廣播,動態註冊是串行廣播。

 

2、SystemUI與FaceId Service長期保持連接。

       SystemUI與FaceId是通過AIDL來通信的, 優化前,SytemUI每次和FaceId通信完畢後都會斷開連接,這樣就導致在下次使用人臉解鎖時,必須重新建立連接,會有一定程度的延遲。優化的方法就是讓SystemUI和FaceId保持長久的連接。當然這一點縮短的時間並不太多。

 

3、使用Camera2 API代替Camera1 API

      系統提供了Camera API-2,是官方對API-1的優化,性能更穩定,使用起來也更加方便。官方並沒有明確說明使用API-2會比API-1更加快速,但實際開發中發現,使用API-2替換後,整個開啓預覽和開啓相機的過程縮短了150ms左右。

 

4、提高相機幀率,儘量減少人臉解鎖算法的等待時間

       人臉解鎖的核心流程是:SDK會預先錄入使用者的人臉數據,在需要解鎖時,相機通過攝像頭以一定的幀率獲取圖像信息,通過API中的回調將圖像信息傳遞給SDK。SDK中封裝了人臉匹配算法,該算法會將相機傳遞的圖像信息和預存的人臉數據進行匹配,並根據匹配結果返回對應的值,比如環境太黑、檢測不到人臉、和預存的不是同一個人、匹配成功等各種匹配結果,都有一個數字與之對應。

       SDK在匹配時,如果成功,一次匹配的時間大約是30ms,如果是失敗的匹配,一次匹配大約50ms~100ms不等(在匹配過程中,如果有新的圖像數據傳遞過來,會被過濾掉)。而平常使用時常常不能一次匹配成功,本次匹配失敗後,很快從相機拿下一筆圖像來匹配,直到在指定時間(設置的是5s)內匹配成功。爲了能夠讓本次匹配失敗後很快拿到下一筆圖像,這就要求相機提高獲取圖像的幀率。這一點督促相機團隊的同事,修改相機參數,綜合考慮之下,取了15ms每幀的頻率。

 

5、合理設置相機的初始曝光值

       相機一般會默認設置一個曝光值,在不同環境中使用時,再根據周圍環境來調整,以適應周圍的光照環境。如果默認的曝光值設置不合適,會導致剛開啓相機時,得到的前幾筆圖像要麼太暗,要麼太亮,需要自我調整達到一個高質量的狀態。

       在優化前,由於對默認的曝光值設置不合理,導致開啓人臉解鎖功能時,即便是很正常的光照環境下,面對正確的人臉時,前面多次匹配都因爲圖像質量太差,導致匹配失敗。每次匹配失敗都會浪費50~100ms的時間,這就導致每次解鎖成功前,都會浪費300ms甚至更多的時間在相機自身調整曝光值上。

       在後面做優化時,通過大量的測試和分析log,發現了每次匹配都不能一次成功的問題,然後將相機提供的數據轉爲圖片,才發現圖像的質量問題。後來和相機團隊的同事,共同調試,得到一個比較合適的初始曝光值,解決了這個問題。

 

6、在啓動人臉解鎖時啓動CPU拉頻,併合理處理速度和省電之間的關係

       人臉解鎖算法執行是一個高密集計算的操作,爲了提高解鎖的速度,優化過程中採用了調度CPU最大核,並提高CPU頻率的做法,使得匹配的速度有所提高。

       調度CPU最大核並提高CPU頻率,是一個非常耗電的過程。爲了更好地平衡匹配速度和省電,這裏又做了一個設計:人臉解鎖超時時間設置的是5s,但實際上,如果周圍環境正常,且是正確的人臉,大部分場景下都能在前1s內解鎖完成,只有在環境異常或者非正確人臉的時候,纔會在1s後還需要匹配,此種場景能解鎖的概率就比較小了。所以這裏的處理方法是,在人臉解鎖的前1s調度CPU最大核,如果還沒有解鎖,則將CPU調回正常,而不是一直都使用CPU大核和高頻。

 

7、合理使用並行代替串行

       人臉匹配成功後,就可以立刻走解鎖流程,並調用相機的關閉方法,而關閉相機需要150ms的時間。優化前原開發者採用的是串行的方式,也就是在人臉匹配完成後,在同一個線程中調用了關閉相機操作,相機關閉後才走鎖屏界面消失的流程。這個優化點應該是很明顯的,關閉相機的操作放在單獨的一個線程去執行就可以了,這樣一來就能夠再優化150ms的時間。至於原開發者爲什麼要採用串行,不得而知。

    

       當然,優化過程還有其他很多的細節,比如一些流程的時間複雜度優化,非必要流程的精簡,要求sdk人臉匹配算法做優化,新手機中使用了性能更好的CPU、相機硬件等。

       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章