背景面试
写这篇文章,主要是为了之后面试方便。由于我简历上写了,上一份工做的最大亮点是将人脸解锁的速度由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、相机硬件等。