有趣的无限缓存OOM现象

news2025/1/15 6:26:34

作者:邹阿涛涛涛涛涛涛

想必大家都知道OOM是啥吧,我就不扯花里胡哨的了,直接进入正题。先说一个背景故事,我司app扫码框架用的zxing,在很长一段时间以前,做过一系列的扫码优化,稍微列一下跟今天主题相关的改动:

1.串行处理改成并发处理,zxing的原生处理流程是通过CameraManager获取到一帧的数据之后,通过DecodeHandler去处理,处理完成之后再去获取下一帧,我们给改成了线程池去调度:

  • 单帧decode任务入队列之后立即获取下一帧数据
  • 二维码识别成功则停止其他解析任务

2.为了有更大的识别区域,选择对整张拍摄图片进行解码,保证中心框框没对准二维码也能识别到

现象

当时测试反馈,手上一个很古老的 Android 5.0 的机器,打开扫一扫必崩,一看错误栈,是个OOM

机器找不到了,我就不贴现象的堆栈了(埋在时光里了,懒得挖了)。

排查OOM三板斧

板斧一、 通过一定手段,抓取崩溃时的或者崩溃前的内存快照

咦,一年前的hprof文件还在?确实被我找到了。。。

从图中我们能获得哪些信息?

  1. 用户OOM时,byte数组的 java 堆占用是爆炸的
  2. 用户OOM时,byte数组里,有大量的 3Mbyte数组
  3. 3Mbyte 数组是被 zxingDecodeHandler$2 引用的

板斧二、从内存对照出发,大胆猜测找到坏死根源

我们既然知道了 大对象 是被 DecodeHandler$2 引用的,那么 DecodeHandler$2 是个啥呀?

mDecodeExecutor.execute(new Runnable() {
            @Override
            public void run() {
                for (Reader reader : mReaders) {
                    decodeInternal(data, width, height, reader, fullScreenFrame);
                }
            }
        });

所以稍微转动一下脑瓜子就能知道,必然是堆积了太多的 Runnable,每个Runnable 持有了一个 data 大对象才导致了这个OOM问题。

但是为啥会堆积太多 Runnable 呢?结合一下只有 Android 5.0 机器会OOM,我们大胆猜测一下,就是因为这个机器消费(或者说解码)单张 Bitmap 太慢,同时像上面所说的,我们单帧decode任务入队列之后立即获取下一帧数据并入队下一帧decode 任务,这就导致大对象堆积在了LinkedBlockingDeque中。

OK,到这里原因也清楚了,改掉就完事了。

板斧三、 吃个口香糖舒缓一下心情

呵呵…

解决方案

解决方案其实很简单,从问题出发即可,问题是啥?我生产面包速度是一天10个,一个一斤,但是一天只能吃三斤,那岂不就一天就会多7斤囤货,假如囤货到了100斤地球会毁灭,怎么解决呢?

  1. 吃快点,一天吃10斤
  2. 少生产点,要么生产个数减少,要么生产单个重量减少,要么二者一起
  3. 生产前检查一下吃完没,吃完再生产都来得及,实在不行定个阈值觉得不够吃了再生产嘛。

那么自然而然的就大概知道有哪几种解决办法了:

  1. 生产的小点 - 隔几帧插一张全屏帧即可(如果要保留不在框框内也能解码的特性的话)
  2. 生产前检查一下吃完没 - 线程池的线程空闲时,才去 enqueue decode 任务
  3. 生产单个重量减少 - 限制队列大小
  4. blalala

总结

装模作样的总结一下。

这个例子是一年前遇到的,今天想水篇文章又突然想到了这个事就拿来写写,我总结为:线程池调度 + 进阻塞队列单任务数据过大 + 处理任务过慢

线程池调度任务是啥场景?

  • 有个 Queue,来了任务,先入队
  • 有个 ThreadPool ,空闲了,从 Queue 取任务。

那么,当入队的数据结构占内存太大,且 ThreadPool 处理速度小于 入队速度呢?就会造成 Queue 中数据越来越多,直到 OOM

扫一扫完美的满足了上面条件

  • 入队频率足够高

  • 入队对象足够大

  • 处理速度足够慢。

在这个例子中,做的不足的地方:

  1. 追求并发未考虑机器性能

  2. 大对象处理不够谨慎

当然,总结是为了避免未来同样的惨案发生,大家可以想想还会有什么类似的场景吧,转动一下聪明的小脑袋瓜~

为了帮助到大家更好的全面清晰的掌握好性能优化,准备了相关的核心笔记(还该底层逻辑):https://qr18.cn/FVlo89

性能优化核心笔记:https://qr18.cn/FVlo89

启动优化

内存优化

UI优化

网络优化

Bitmap优化与图片压缩优化https://qr18.cn/FVlo89

多线程并发优化与数据传输效率优化

体积包优化

《Android 性能监控框架》:https://qr18.cn/FVlo89

《Android Framework学习手册》:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/927012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习ts(九)混入

对象混入 使用Object.assign()进行对象混入,最后的people会被识别为三种类型的联合类型 类混入 使用implement并非extnds实现混入。 属性在混入类里面定义,分别在类中占位,方法分别在类中定义,在混合类中占位。这告诉编译器这…

自动化的驱动力,工控机助您实现智能生产!

“智能工厂建设如火如荼,部分成果已经落地,在大规模资金投入的市场催化下,海尔、海信等制造企业通过智能工厂手段推进生产效率成倍增长的新闻层出不穷。在工业4.0时代,“中国制造2025”战略中,智能工厂构建都是其中不可…

激活函数总结(十九):激活函数补充(ISRU、ISRLU)

激活函数总结(十九):激活函数补充 1 引言2 激活函数2.1 Inverse Square Root Unit (ISRU)激活函数2.2 Inverse Square Root Linear Unit (ISRLU)激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函…

用docker-compose搭建LNMP

docker-compose搭建LNMP 一、compose 的部署1.Docker Compose 环境安装 二、编写Docker Compose1.准备依赖文件,配置nginx2.配置mysql3.配置php4.编写docker-compose.yml5.执行6.查看 一、compose 的部署 (1)公司在实际的生产环境中,需要使用…

磁盘阵列/视频集中存储/安防监控视频智能分析平台新功能:人员聚集

人工智能技术已经越来越多地融入到视频监控领域中,近期我们也发布了基于AI智能视频云存储/安防监控视频AI智能分析平台的众多新功能,该平台内置多种AI算法,可对实时视频中的人脸、人体、车辆、物体等进行检测、跟踪与抓拍,支持口罩…

Linux上实现分片压缩及解压分片zip压缩包 - 及zip、unzip命令详解

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…

LiveNVR监控流媒体Onvif/RTSP功能-支持语音对讲支持非国标摄像头SDK语音对讲GB28181级联国标平台非国标转国标语音对讲

LiveNVR支持语音对讲支持非国标摄像头SDK语音对讲GB28181级联国标平台非国标转国标语音对讲 1、确认摄像头是否支持对讲2、摄像头视频类型复合流3、通道配置SDK接入4、视频广场点击播放5、相关问题5.1、如何配置通道获取直播流?5.2、如何GB28181级联国标平台&#x…

AD(第四部分---网表导入及模块化布局设计)

第四部分:网表导入及模块化布局设计 21.导入常见报错解决方法(unknow pin及绿色报错等) 将原理图导入到PCB: 在原理图界面点击右上角设计 导出后,若出现如下错误,则说明没有0805C的电容: 没有电容应该怎么办呢?需要进…

10 倍性价比,万物新生基于 StarRocks 无缝直替 Trino

小编导读: 万物新生成立于2011年,定位为“互联网环保”类型的循环经济企业,是中国最大的二手电子产品交易与服务平台。万物新生集团旗下4大业务线包含:爱回收、拍机堂、拍拍、海外业务 AHS Device。万物新生集团秉承“让闲置不用…

raft算法学习备忘

一致性共识算法 参考:分布式一致性算法应用场景,写了为什么需要共识算法,以及相比于mysql这些主从同步方式的区别。 raft算法简介 一种分布式一致性共识算法的实现方式,机制相比于其它例如paxos来说无论从可读性还是实现机制上要简单很多&…

MQTT协议抓包

MQTT通讯协议的特点 1. 概述 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做…

html-dom核心内容--四要素

1、结构 HTML DOM (文档对象模型) 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。 2、核心关注的内容:“元素”,“属性”,“修改样式”,“事件反应”。>四要素…

详解numpy.random.shuffle函数

文章目录 函数原型参数解析该函数的注意事项例子示例代码示例结果 参考 numpy的random模块中的shuffle函数用于np.ndarray数组中的元素打乱顺序,进打乱多维数组的第一维顺序。本博客详细节将该函数的API,并给出示例代码和结果。 函数原型 random.shuff…

【计算机网络】HTTPs 传输流程

HTTPS和HTTP的区别 1、HTTP协议传输的数据都是未加密的,是明文的,使用HTTP协议传输隐私信息非常不安 HTTPS协议是由SSLHTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。 2、HTTPS协议需要到CA申请证书,一般…

【C++】开源:Box2D动力学库配置与使用

😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍Box2D动力学库配置与使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下&#xff0c…

LiveNVR通过海康SDK实现Web无插件播放并实现双向语音对讲的注意事项和配置方法

1、确认摄像头是否支持对讲 可以访问摄像头自己的页面,看是否能够对讲。可以看摄像头的音频编码页面,看看音频输入有没有mic的音频输入。如下: 2、摄像头视频类型复合流 确认摄像头的视频类型,是否是复合流。 3、通道配置SD…

第三批广东省智能制造生态合作伙伴名单公布,科东软件再获殊荣!

8月22日,广东省工业和信息化厅公布了第三批广东省智能制造生态合作伙伴名单。科东软件凭借多年在工业操作系统领域的技术积累和创新实力,成功入选广东省智能制造生态合作伙伴名单(关键软件领域)。 智能制造生态合作伙伴是指为广东…

实现高效消息传递:使用RabbitMQ构建可复用的企业级消息系统

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

计算机竞赛 基于卷积神经网络的乳腺癌分类 深度学习 医学图像

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度,召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…

ssh免密配置后没生效问题

一、背景 3台linux服务器搭建集群需要互相做ssh免密,按正常流程操作后验证,免密未生效,还需要输入密码,开始了一路问题定位的历程。。。。 原理请移步 linux服务配置ssh免密 二、思路 (一)确认免密操作…