为了更好地了解下文内容,我们先简单介绍一下Binder:
Binder属于一种IPC通信机制,是用来实现不同进程间通信的,主要由ServiceManager、Server(服务端)、Binder 驱动、Client(客户端)4 部分构成,其中Client、Server、Service Manager运行在用户空间,Binder驱动运行在内核空间。一次完整的 Binder IPC 通信过程通常如下:
1)Binder 驱动在内核空间创建一个数据接收缓存区;
2)在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系;
3)发送方进程通过系统调用 copy_from_user()将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,完成一次进程间的通信。
Binder共享内存耗尽的影响:
Binder调用耗时长,甚至失败;
若是用户操作的关键流程,则会导致卡顿发生。
优化建议:
及时释放data(Server端)或reply(Client端),建议用AIDL框架;
Binder接口设计时避免大数据的参数传递,若有需要可用Ashmem传递;
避免短时间内大量线程同时并行调用某Server,若有需要,需做削峰处理。
02 Binder线程池耗尽
Server端有一定数量的Binder线程池来响应Client的调用,一个进程的Binder线程数默认最大是16(1个主线程和15个非主线程),超过的请求会被阻塞等待空闲的Binder线程,即Binder线程池耗尽会导致后面的调用被阻塞。
创建大量BpBinder或Binder对象的影响:
内存占用,频繁GC,甚至因OOM而闪退;
整机卡顿。
优化建议:
一个Service仅一个Binder对象实例,按使用场景和生命周期合并Service;
及时释放不再使用的BpBinder。
04 使用多个ServiceConnection对象Bind同一个Service
ServiceConnection其实也是一个Service,提供给AMS维护,用于管理目标Service的回调。同一个ServiceConnection对象可以管理多个Service,Client端已做到对不同Service的复用,AMS仅维护一个IServiceConnection;但不同ServiceConnection对象没有做到复用,即使是同一个Service。
随用随获取系统服务影响:
不必要的跨进程同步调用耗时1ms左右,有些甚至达到s级(logcat -b events -s service_manager_slow);
增加系统负荷。
优化建议:
一次获取成功后本地缓存;
通过IBinder的linkToDeath机制感知到服务的退出,服务退出后清除本地IBinder缓存,下次需要时再次向Servicemanager获取。
除了上述的不良实现外,还有组件对象泄漏(原生的removeContextRegistrations中有对SC、Receiver和Window泄漏的检查)、系统核心进程调用非ONEWAY的IPC接口(会带来核心进程卡死的风险)以及HIDL仅用于跨进程间调用(对于Client和Server共进程的场景,不要使用HIDL)等。
到这里,APP性能设计及优化专题告一段落,欢迎大家后台留言,发表您对文章的见解,或反馈您想查看的内容,希望我们一起进步哦~
最后: 自行领取一份216页软件测试工程师面试宝典文档资料【免费的】。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联 程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览92118 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!