iOS 内存监控与治理(三)- 设计一款内存问题(FOOM)检测工具

前言

前面的章节,我们已经对内存机制和内存管理有了一定的了解,现在我们将正式进入主题 - 如何设计一款内存检测工具。由于DEBUG环境已有众多的第三方开源工具以及instruments,所以我们的侧重点放在了线上监控。

目标

内存问题造成的后果最常见且最严重的莫过于造成OOM崩溃了,上一章我们对OOM进行了详细的解释,这里引入一个新的概念FOOM:发生在前台的OOM。FOOM由于发生在前台,对于用户的直观感受来说就是发生了Crash,所以我们的工作重心就在于处理FOOM。

  • 监控到线上用户发生了FOOM

  • 当发生FOOM时,期望上报一些内存相关的数据,辅助定位FOOM的原因

SDK功能设计

功能一:用户内存占用统计

APP 占用的内存,一般有resident_size、phys_footprint、virtual_size等统计方式,这里就不一一展开了,一般认为phys_footprint 是最贴近APP 真实内存占用的数据。内存占用数据统计可以开启定时器定时的Log数据,也可以在特定场景下Log数据,比如在ViewDidAppear等。

- (NSInteger)getAllMemoryOccupy {
    
    task_vm_info_data_t vmInfo;
    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
    kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
    if (kernelReturn != KERN_SUCCESS) {
        return 0;
    }
    int64_t memoryUsageInByte = (int64_t) vmInfo.phys_footprint;
    return memoryUsageInByte/1024/1024;
}
功能二:监控线上用户发生FOOM

目前采用的是FB的排除法。每次 APP 冷启动时,判断上次 APP 运行过程中记录的特定值,排除掉其他崩溃原因后,得出上次发生了FOOM 的结论。

checkoom.jpeg
功能三:上报可疑堆栈

上报可疑堆栈具体是指在程序运行的过程中,不断记录存活内存的相关信息,同时通过backtrace函数拿到对应的堆栈信息,对这些信息做筛选聚合处理后,写入到本地文件中,当判断发生了FOOM时再上报这些数据。

我们首先看两个 libmalloc 源码中stack_logging_disk.c定义的两个接口

// We set malloc_logger to NULL to disable logging, if we encounter errors
// during file writing
typedef void (malloc_logger_t)(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t result, uint32_t num_hot_frames_to_skip);
extern malloc_logger_t *malloc_logger;

extern malloc_logger_t *__syscall_logger;   // use this to set up syscall logging (e.g., vm_allocate, vm_deallocate, mmap, munmap)

当malloc_logger和__syscall_logger函数指针不为空时,malloc/free、vm_allocate/vm_deallocate等内存分配/释放通过这两个指针通知上层,这也是内存调试工具malloc stack的实现原理。有了这两个函数指针,我们很容易记录当前存活对象的内存分配信息(包括分配大小和分配堆栈)。分配堆栈可以用backtrace函数捕获,但捕获到的地址是虚拟内存地址,不能从符号表dsym解析符号。所以还要记录每个image加载时的偏移slide,这样符号表地址=堆栈地址-slide。

关于 malloc_logger和syscall_logger 回调的内存分配,可以简单的理解为,malloc_logger 回调堆内存对象,syscall_logger 回调虚拟内存对象,如下俩图所示:NSArray的创建及CALayer 渲染

arrayAlloc.png
layerRender.png

有了系统底层的函数回调后,加上backtrace 获取到的堆栈地址,我们就可以根据这些参数设计一套堆栈聚集上报体系。总的来说就是当内存分配的堆栈相同,且同堆栈的内存大小累积值达到设定好的阈值时,写入本地mmap文件,下次冷启动时,判断是否发生了FOOM,确认发生FOOM 时 上报该堆栈。

核心数据流向如下图:

image-20211022172158955.png

注:__syscall_logger 属于私有api,提审时需移除,线上SDK 只包含堆内存的监控

堆栈上报的功能主要来源于腾讯开源的内存监控SDK Tencent/OOMDetector

此外,附上libmalloc开源文档

功能四:OC 存活对象监控

通过hook NSObjectallocWithZonedealloc来统计当前APP 存活的OC 对象,比如统计出所有存活的ViewController 类型对象,这一块数据处理逻辑与上面的可疑堆栈数据上报处理逻辑保持一致。

功能五:内存占用足迹

在非 系统的以及UINavigationController,UITabBarController 的控制器生命周期方法 viewDidLoad 及 viewDidApper 方法记录APP 此刻占用的内存,当然我们的SDK 可以只保留最后一部分数据,完整的数据可以打印在用户日志中。

结语

一个APP 占用过多内存资源的原因是多种多样的,有可能是某些场景存在内存泄漏,有可能是缓存了很多动效文件。如果有办法能够获取到内存异常时所有的内存结点及引用关系那自然是最理想的结果,可惜APP 发生OOM时,官方没有提供接口来监控它,我们只能自行设计合适的内存监控方案,上文的这些功能也只是抛砖引玉,希望大家多多讨论。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容