前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >APP性能设计及优化专题——影响性能的不良实现

APP性能设计及优化专题——影响性能的不良实现

作者头像
软件绿色联盟
发布2022-06-30 17:42:56
8230
发布2022-06-30 17:42:56
举报

继介绍性能设计概述性能优化建议后,本文将重点介绍影响性能的不良实现,主要包含Binder共享内存耗尽、Binder线程池耗尽、创建大量BpBinder或Binder对象等方面。

为了更好地了解下文内容,我们先简单介绍一下Binder:

【注】由于Binder机制的复杂性,这里不展开介绍,仅简单概括,便于更好理解本文内容。

Binder属于一种IPC通信机制,是用来实现不同进程间通信的,主要由ServiceManager、Server(服务端)、Binder 驱动、Client(客户端)4 部分构成,其中Client、Server、Service Manager运行在用户空间,Binder驱动运行在内核空间。一次完整的 Binder IPC 通信过程通常如下:

1)Binder 驱动在内核空间创建一个数据接收缓存区;

2)在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系;

3)发送方进程通过系统调用 copy_from_user()将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,完成一次进程间的通信。

由于Binder在跨进程通信过程中担任着极其重要的作用,任何流程或异常都会带来负面影响。

  1. Binder共享内存耗尽

Binder的性能(减少一次copy_to_user)和安全是最大优势,但由于Binder在内核和用户态都对传输的数据量有限制,因此要避免通过Binder传输大量数据。一个进程用于接收Binder数据的共享内存为1M-8K,对于oneway要减半。同时,Binder driver也有4M上限的限制,当多个线程共用这块共享内存时,一旦driver发现数据接收方共享内存不够,就会返回错误。

Binder共享内存耗尽的影响:

  • Binder调用耗时长,甚至失败;
  • 若是用户操作的关键流程,则会导致卡顿发生。

优化建议:

  • 及时释放data(Server端)或reply(Client端),建议用AIDL框架;
  • Binder接口设计时避免大数据的参数传递,若有需要可用Ashmem传递;
  • 避免短时间内大量线程同时并行调用某Server,若有需要,需做削峰处理。

2. Binder线程池耗尽

Server端有一定数量的Binder线程池来响应Client的调用,一个进程的Binder线程数默认最大是16(1个主线程和15个非主线程),超过的请求会被阻塞等待空闲的Binder线程,即Binder线程池耗尽会导致后面的调用被阻塞。

Binder线程池耗尽的影响:

  • 同步调用的Client端被阻塞,若是用户操作的关键流程中,则发生卡顿现象;
  • system_server等系统关键服务进程的Binder线程池耗尽,则造成整机卡顿。

优化建议:

  • 避免短时间内大量线程同时并行调用某Server,若有需要则需做削峰处理;
  • 提升Binder接口实现的执行效率。

3. 创建大量BpBinder或Binder对象

BpBinder是客户端中的Binder引用,保存着目标服务的handle信息,即服务端的Binder实体的引用信息,用于查询内核中的Binder节点,并同Binder实体通信。

系统并未限制Server端的Binder对象创建,理论来说可以大量创建,但一个Service应该仅创建一个Binder对象,BpBinder对象有上限6000/2500个,多了会被杀掉,因此建议同一个Service的BpBinder实现进程内共用。

创建大量BpBinder或Binder对象的影响:

  • 内存占用,频繁GC,甚至因OOM而闪退;
  • 整机卡顿。

优化建议:

  • 一个Service仅一个Binder对象实例,按使用场景和生命周期合并Service;
  • 及时释放不再使用的BpBinder。

4. 使用多个ServiceConnection对象Bind同一个Service

ServiceConnection其实也是一个Service,提供给AMS维护,用于管理目标Service的回调。同一个ServiceConnection对象可以管理多个Service,Client端已做到对不同Service的复用,AMS仅维护一个IServiceConnection;但不同ServiceConnection对象没有做到复用,即使是同一个Service。

使用多个ServiceConnection对象Bind同一个Service的影响:

  • 增加AMS的维护负担,Service的启动/退出都会持有AMS锁后遍历SC;
  • 长时间持有AMS锁,导致整机卡顿。

优化建议:

  • 复用同一个ServiceConnection对象,特别是同一个Service;
  • 监听Service的死亡回调,若有需要可立即重新Bind;
  • 及时unbind不再使用的Service。

5. 随用随获取系统服务

系统服务由ServiceManager维护,获取系统服务IBinder的过程也是一次跨进程Binder调用。应用常用的系统服务在应用进程启动时就已由ATMS带过去了,而其他系统服务系统对普通应用使用hiden接口来限制。当出现频繁调checkService接口的,主要是系统服务或系统应用。

随用随获取系统服务影响:

  • 不必要的跨进程同步调用耗时1ms左右,有些甚至达到s级(logcat -b events -s service_manager_slow);
  • 增加系统负荷。

优化建议:

  • 一次获取成功后本地缓存;
  • 通过IBinder的linkToDeath机制感知到服务的退出,服务退出后清除本地IBinder缓存,下次需要时再次向Servicemanager获取。

除了上述的不良实现外,还有组件对象泄漏(原生的removeContextRegistrations中有对SC、Receiver和Window泄漏的检查)、系统核心进程调用非ONEWAY的IPC接口(会带来核心进程卡死的风险)以及HIDL仅用于跨进程间调用(对于Client和Server共进程的场景,不要使用HIDL)等。

到这里,APP性能设计及优化专题告一段落,欢迎大家后台留言,发表您对文章的见解,或反馈您想查看的内容,希望我们一起进步哦~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件绿色联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档