踩过的一个android原生“坑”

来源:互联网 发布:jquery 1.11.1.min.js 编辑:程序博客网 时间:2024/06/10 19:56

“坑”描述:

在对我们自己研发的一款android终端进行camera拍照压力测试时,发现当拍照张数达到几万张时,查看内存占用情况,发现内存泄露。

填“坑”:

frameworks/base/core/jni/android/graphics/YuvToJpegEncoder.cpp

bool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width,        int height, int* offsets, int jpegQuality) {    jpeg_compress_struct    cinfo;    skjpeg_error_mgr        sk_err;    skjpeg_destination_mgr  sk_wstream(stream);    cinfo.err = jpeg_std_error(&sk_err);    sk_err.error_exit = skjpeg_error_exit;    if (setjmp(sk_err.fJmpBuf)) {        return false;    }    jpeg_create_compress(&cinfo);    cinfo.dest = &sk_wstream;    setJpegCompressStruct(&cinfo, width, height, jpegQuality);    jpeg_start_compress(&cinfo, TRUE);    compress(&cinfo, (uint8_t*) inYuv, offsets);    jpeg_finish_compress(&cinfo);    return true;}

坑就在上面这个接口函数中:
熟悉libjpeg的同学会注意到,上面的接口在调用完jpeg_finish_compress()后,没有调用jpeg_destroy_compress(),这个接口是释放压缩工作过程中所申请的资源,主要就是jpeg压缩对象。
由于android原生接口中,没有调用jpeg_destroy_compress()导致每次泄露几十个字节,当拍照数量达到万级时,才会有所察觉。

怎么找到这个坑的:

这个过程后面有时间会详细写下,目前心得就是模块的架构十分重要,对这种数据流的控制,pipeline方式是比较好的方案,因为可以明确输入输出,然后通过伪造输入输出对各个模块进行单独的压力测试。最难控制的就是“洋葱”式的包裹调用,要像“剥洋葱”一样一层层的剥离十分麻烦。

你的android机上有这个问题吗:

9成的概率下你的手机应该不会有这个问题,因为上面我讲到是在我们做的一款终端上发现的问题,我们的终端芯片方案比较挫,没有硬编码模块,导致使用了android的软编码方案,也就用到libjpeg这个模块,也就触发了上面问题函数接口的调用。

牢骚:

做底层系统开发就是这样,一个bug耗费了很久的时间去测试,查找,验证。一层层剥离模块,逐步定位问题的大概位置,到最后精确定位问题,并解决,bug的解决可能就是一行代码的事(上面就加上destroy接口即可),但着实耗费了不少时间,如果按照代码行数计算kpi,这个performance应该是差的可以了。

0 0
原创粉丝点击