范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

百度APPiOS端内存优化实践内存管控方案

  一.
  背景   随着业务的发展,百度APP有很多大内存业务场景如直播、短视频、小程序、百度识图等,通过线上页面统计数据得知超过150M页面有40个,耗内存最多的页面有400M。单个页面不会有内存或者稳定性问题,但是当用户浏览了很多页面之后,累加起来内存已经很高了,再加上我们为了追求秒开,经常采用的思路是以空间换取时间,从而导致APP处于一个内存高水位状态,在这种情况下如果打开一个大内存页面,中低端机极大概率会出现OOM类型的崩溃。   内存管控方案应运而生,该方案重点解决的问题是在内存水位很高的情况下,保证APP稳定性又兼顾用户体验,延长APP使用时长同时避免OOM。   该技术方案在百度APP于22年Q1顺利上线,随着基础服务层和越来越多的业务线接入,尤其是OOM频发的页面接入后,在降低OOM率方面发挥了重大作用,效果非常明显。   二.
  技术方案综述   内存管控整体方案架构图如下所示:   实时监控APP内存: 在APP运行阶段不断监控内存变化。重点关注两个问题,第一,选取合适的能反映APP内存的指标,第二、实时性必须满足要求,同时不能引入额外的性能问题。 页面内存预测: 根据历史经验和线上数据,我们可以预测将要打开新页面后APP占用内存大小,结合当前内存我们可以实时计算出应用新开当前页面后自身占用的内存大小,举个例子,当前页面占用内存400M,通过线上历史经验数据我们知道新页面需要占用内存是300M,那么新开一个页面后,APP内存700M。 内存水位判断: 根据对当前APP内存状态的监控,能够判断出用户内存所处的水位状态,如安全水位和危险水位,安全水位是指当前APP内存足够,可完全按照业务需求分配内存,危险水位是指目前APP很容易出现OOM,必须马上释放内存缓存。 频率控制: 因为每隔3S做一次内存检测,当处于危险水位时,会通知APP各个模块做内存释放,但内存释放也是需要时间的,并且不一定会立马降低到安全水位,如果接下来还是每隔3S通知各模块做内存释放,其实是一种资源浪费,频繁的内存释放操作会给APP性能带来损耗,所以通过频率控制模块既能最大限度地释放内存,又实现APP性能最小损失。 危险水位报警: 当APP的内存处于危险水位的状态时,会向基础服务层和业务两个层面发送报警通知,对于基础服务层来说,百度APP主要做了图片内存和NSURLCache内存自动回收,全局生效;对于业务层来说,主要针对内存大户且OOM率较高的页面做了内存释放操作,如小程序页面,收到内存报警时,会将缓存的处于非活跃状态的页面做清理操作,对于其他业务同样道理,清理业务自身的数据缓存和其他内存缓存。 主动降级: 是指业务层在分配较大内存时,先判断当前APP所属的内存水位等级,若处于危险水位,业务做降级分配较小内存,若处于安全水位,做全量内存分配。目前百度APP的识图和数字人业务已接入此方案,对于百度识图场景,做多模态图片识别加载算法模型文件较大,处于危险水位时加载兜底模型,以业务能用为标准,其他场景类似。   三.
  与内存报警的区别   目前iOS系统中存在类似的方案,专业名称为内存报警机制,当设备可用内存下降到到危险状态时,Mach系统的pageout 守护程序会查询进程列表及其驻留页面数,向驻留页面数最高的进程发送NOTE_VM_PRESSURE ,被选中的进程会响应这个压力通知,本质上就是APP收到系统的didReceiveMemoryWarning 内存警告,APP释放部分内存达到降低手机内存负载的目标。有人会问iOS系统提供了内存报警通知,为什么我们还会做貌似类似的事情,这是因为我们对系统的内存报警机制做了如下 两点补充 : 内存报警机制是内存极其危险的时候才发出的,尤其是对于低端机而言非常致命,因为APP来不及释放内存到安全水位就已经OOM了。在实践开发过程中,对低端机(iPhone8以下)测试结果发现,当收到内存报警时,APP实际可使用内存 (可用内存减去已用内存) 没有超过100M,但是目前手百APP大于150M页面就有40个,当收到内存警告前后,随便打开上述40个大页面中的任何一个页面,APP根本没有来得及处理警报应用就会崩溃。相反,百度APP内存管控方案在制定危险水位时考虑到这种情况,适当预留了较大空间,让APP更从容地释放内存。 内存报警机制没有提供获取APP实时内存状态的功能,在实践中经常会遇到大块内存分配的场景,较为常见场景如在中低端机端智能场景中,加载大模型到内存时,因为不知道内存当前处于危险状态还是安全状态,分配较大内存会出现内存峰值瞬时上涨到高点,中低端机手机设备直接OOM,在整个过程中也根本没有收到过内存报警。内存管控方案弥补了这一不足,通过实时获取内存状态,不同机型不同设备设置不同危险水位级别,在分配较大内存时,先判断APP内存状态,若处于危险水位时,业务线开发可以走降级逻辑,降低对内存消耗,减少OOM风险。   四.
  实时监控APP内存   百度APP实时监控内存采用如下方案:在子线程开启定时器,每隔3S去采样一次内存phys_footprint字段数据,以此作为衡量的内存的唯一指标,其他字段值一律不要获取,因为多增加一个变量会多增加CPU计算量。实践数据表明,第一、单次获取phys_footprint耗时小于1us,每隔3S获取phys_footprint没有引起CPU占比的涨幅,也就是说不会带来性能问题;第二、3S的采样周期实时性完全满足我们工程的要求,正常情况下,开启一个页面到页面可交互需要1.5S+,采样周期如果太长,会存在页面内存已经飙升但是还没来得及做管控,采样周期太短会浪费过多的CPU资源。   为什么我们选用phys_footprint作为内存衡量指标,而不用其他字段,需要重点解释一下。iOS端所有的内存相关指标都集中在task_vm_info结构体中,下载XNU最新开源代码 (https://opensource.apple.com/source/xnu/) ,代码路径:osfmk/mach/task_info.h,具体字段值如下所示: struct task_vm_info { mach_vm_size_t virtual_size; /* virtual memory size (bytes) */ integer_t page_size; mach_vm_size_t resident_size; /* resident memory size (bytes) */ /* 省略 */ mach_vm_size_t phys_footprint; /* 省略 */ }   iOS开发演变的这几年历程中,受Android端内存指标影响,我们先后使用过各种内存指标,常见的如virtual_size( 虚拟内存)、resident_size(驻留内存)和phys_footprint,那究竟使用哪个指标是合理的?我们知道iOS使用的是低内存清理机制叫Jetsam,这个机制有点类似于Linux的"Out-of-Memory"杀手,当内存压力过大时,Jetsam会把一些优先级不高或者占用内存过大的进程杀掉。就是说内存处于危险状态时Jetsam决定kill哪个进程,因此Jetsam衡量内存水位指标绝对是众多内存指标中最为合理的一项,接下来我们看Jetsam机制源码。   我们再次回到XNU源码中,查看代码bsd/kern/kern_memorystatus.c,重点查看函数 memorystatus_kill_hiwat_proc,这是jetsam核心代码,用于kill高内存分配进程的关键函数,具体实现如下所示: static boolean_t memorystatus_kill_hiwat_proc(uint32_t *errors, boolean_t *purged, uint64_t *memory_reclaimed) { next_p = memorystatus_get_first_proc_locked(&i, TRUE); while (next_p) { /* 省略 */ footprint_in_bytes = get_task_phys_footprint(p->task); skip = (footprint_in_bytes <= memlimit_in_bytes); if (skip) { continue; } else { memorystatus_kill_proc(p, kMemorystatusKilledHiwat, jetsam_reason, &killed, &footprint_in_bytes); /* 省略 */ } }   首先通过memorystatus_get_first_proc_locked去优先级队列里面取出优先级最低的进程,如果内存超过阈值,将通过memorystatus_kill_proc杀掉这个进程,否则跳过取下一个进程。我们看到Jetsam是通过 get_task_phys_footprint方法获取内存水位来决定是不是需要kill该进程,因此使用phys_footprint作为APP内存指标是最合适的。   关于 phys_footprint 的定义,我们回到 XNU 源码中,查看代码 osfmk/kern/task.c ,有phys_footprint 的注释定义。 * Physical footprint: This is the sum of: * + (internal - alternate_accounting) * + (internal_compressed - alternate_accounting_compressed) * + iokit_mapped * + purgeable_nonvolatile * + purgeable_nonvolatile_compressed * + page_table   phys_footprint = (internal - alternate_accounting) + (internal_compressed - alternate_accounting_compressed) + iokit_mapped + purgeable_nonvolatile + purgeable_nonvolatile_compressed + page_table 。   字段   具体含义   internal   在iOS中表示的就是resident_size驻留内存   internal_compressed   iOS 上没有交换空间机制,取而代之使用Compressed memory,是在内存紧张时能够将最近使用过的内存占用压缩至原有大小的一半以下,并且能够在需要时解压复用   iokit_mapped   io设备映射占用的内存,其实是不能使用purgeable memory的部分   alternate_accounting   iokit映射占用的dirty页   page_table   虚拟地址映射表内存   purgeable_nonvolatile   下面重点介绍   purgeable内存是iOS系统为开发者提供的一层cache机制,分为volatile、empty和non_volatile三种类型,volatile表示该内存资源是暂时不被使用的,系统将在内存吃紧的时候回收掉它,使用这种类型资源前要查询是否已经无效了 (变成empty状态) ;empty表示该内存资源明确不用了需要立即释放;non_volatile表示该内存资源一直有用,不能被回收。volatile和empty状态的资源不计入进程自己的mem footprint,它算系统的cache内存,nonvolatile会算自己进程的内存,被虚拟内存系统回收时不会被换出到磁盘,所以phys_footprint在计算内存时,只计算了nonvolatile类型,对于volatile、empty没做计算。   五.
  页面内存预测   为了能够更精准的对页面的内存进行分析和预测,我们在实时内存监控的基础上,开发了页面内存预测方案。具体来说,在前面通过定时器我们知道了每隔3S手机APP内存状态,本方案通过经验数据直接预测未来一段时间内存的涨幅,让业务线可以更加从容的释放内存。我们知道当新打开一个页面时存在内存飙升的情景,这个时候3S的采样周期未到,内存已经上涨很多,内存管控方案还未生效APP极有可能已经OOM了。我们的方案是通过页面内存计算,在打开新页面前一刻, 就知道接下来页面内存可能会涨到多少,如果进入危险水位,实时释放内存以降低OOM率,通过这种精细化处理进一步提前降低内存峰值。   页面内存计算方案如下所示,首先,当前页面是P1页面,当有页面跳转发生,将要通过push操作进入到P2页面时,记录当前百度APP内存phys_footprint值为M1,当从P2页面同样发生跳转到其他页面时,记录百度APP内存phys_footprint值为M2,那么M2-M1为P2页面内存。   注意,我们只通过push方式统计了页面内存,没有通过pop方式统计,有两个原因,第一、通过线上数据发现,pop方式时因页面已经打开,并且会创建单例导致内存统计存在很多badcase,push方式时页面从未创建也不会有单例,数据相对准确;第二、通过push方式已经可以覆盖所有页面了,pop方式不需要统计。   六.
  制定内存水位   关于内存水位的制定直接决定了本方案实际收益的大小,水位阈值制定太小会导致频繁的内存管控影响业务效果,水位阈值制定的太大,与实际的Jetsam水位线偏离过大,导致内存管控无法生效,可能会出现APP已经OOM了,管控方案还没生效,水位线的制定非常关键。   关于危险水位线的制定,必须结合Jetsam原理,目前苹果官方没有公开Jetsam水位的文档,业界有如下方法解决方案。 丨6.1 通过Jetsam日志获取   具体来说从手机"设置->隐私->分析与改进->分析数据"这条操作路径中,可以拿到JetsamEvent 开头的日志。这些日志中就可以获取一些关于 App 的内存信息,查找崩溃原因时需要关注 per-process-limit 部分的 rpages,其中rpages代表进程占用的内存页数量。pageSize代表当前设备物理内存页的大小,在 JetsamEvent 开头的系统日志里可以找到 pageSize 的值,那么pageSize * rpage的值代表目前该进程OOM时使用的内存大小,可作为进程可用内存的上限。   实际操作过程中,发现此方法可操作性不强,因为同一台手机不同的JetsamEvent日志rpages值变化太大,用iphone12的测试结果显示,从400到800都有,pageSize是固定值16384Byte,按照最高值计算当前 App 的内存限制值:pageSize * rpages / 1024 /1024 =16384 * 800 / 1024 / 1024 = 12.5M,按这个结果iphone12最大的内存阈值是12.5M,置信度明显有问题。   丨6.2通过XNU源码获取内存水位阈值   首先必须越狱手机获取root权限,通过XNU源码中的数据结构、宏定义和函数获取OOM阈值,参考XNU最新开源代码(https://opensource.apple.com/source/xnu/),代码路径:bsd/sys/kern_memorystatus.h,关键数据结构memorystatus_priority_entry,定义如下,其中pid代表进程标识,priority代表JetSam中的优先级,limit就是我们要找的水位线上线。同时,在文件kern_memorystatus.h有如下跟进程优先级相关的宏命令,其中通过MEMORYSTATUS_CMD_GET_PRIORITY_LIST宏定义可以获取进程的优先级列表以及每个进程的内存水位线。 typedef struct memorystatus_priority_entry { pid_t pid; int32_t priority; uint64_t user_data; int32_t limit; uint32_t state; } memorystatus_priority_entry_t; #define MEMORYSTATUS_CMD_GET_PRIORITY_LIST 1 #define MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES 2 #define MEMORYSTATUS_CMD_GET_JETSAM_SNAPSHOT 3 #define MEMORYSTATUS_CMD_GET_PRESSURE_STATUS 4 /* 省略 */   最后通过调用系统函数memorystatus_control的实现可获取memorystatus_priority_entry结构体值,其中limit字段代表水位线, 代码路径:bsd/kern/kern_memorystatus.c int memorystatus_control(struct proc *p __unused, struct memorystatus_control_args *args, int *ret) { /* 省略 */ switch (args->command) { case MEMORYSTATUS_CMD_GET_PRIORITY_LIST: error = memorystatus_cmd_get_priority_list(args->buffer, args->buffersize, ret); break; /* 省略 */ }   实践证明这种方法是可行的,唯一缺点是需要获取root权限,我们要获取不同机型的内存阈值,需要将这些设备全部越狱。 丨6.3百度APP采用的技术方案   百度APP采用的方案是综合百度APP自身的线上业务数据,采用主动触发OOM获取内存阈值方案,结合多方数据最后确定内存危险水位阈值。 丨6.3.1内存数据摸底   通过线上内存采样打点,获取了百度APP不同机型在使用过程中的内存值,然后经过服务端数据聚合,我们明确知道了百度APP在没有发生OOM情况下不同机型的内存最大值,这份线上数据很重要,虽然不是内存阈值的,但是内存阈值肯定是高于该值的。 丨6.3.2页面内存数据统计   技术方案在第五节做过详细介绍,这儿不再赘述,通过服务端对页面内存数据挖掘后,我们明确知道了不同机型新开一个页面时最大的内存涨幅。 丨6.3.3主动触发OOM获取内存值   开启定时器任务每隔1S分配20M内存,示例代码如下所示: int size = 20 * 1024 * 1024; char *info = malloc(size); memset(info, 1, size);   同时监控内存变化,在控制台输出,随着可用内存越来越少,触发Jetsam机制,直到发生OOM,从而得到OOM前内存阈值。 (int64_t)memoryUsage { int64_t memoryUsageInByte = 0; struct task_vm_info info; mach_msg_type_number_t size = TASK_VM_INFO_COUNT; kern_return_t kerr = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &info, &size); if (kerr == KERN_SUCCESS ) { memoryUsageInByte = info.phys_footprint; } return memoryUsageInByte; }丨6.3.4确定内存管控危险水位阈值   经过前面三个步骤,我们获取了不同机型的三个阈值,分别是内存数据摸底阈值、页面内存阈值、主动触发OOM获取的阈值,为了让业务更从容地释放内存, 内存管控阈值为主动触发OOM获取的阈值减去页面内存阈值,如果该值小于内存数据摸底阈值,那么内存数据摸底阈值就是该机型内存管控阈值。   百度APP采用的这个技术方案不需要越狱手机,通过主动触发OOM获取的阈值体现了Jetsam机制,更具有可操作性;同时结合自身线上数据,针对手百场景定制化挖掘。   七.
  总结   最后,总结百度APP内存管控方案具有如下特点: 针对不同机型制定了相应的内存水位可以更加从容地释放内存。本技术方案结合Jetsam机制和百度APP线上内存数据,制定了iPhone各机型允许使用的内存水位线,给业务和框架更大的空间释放和清理内存。 实时内存监控和精细化页面内存预测,在实时内存监控的基础上,开发了页面级的内存度量方案,可以估算出用户在新开一个页面内存涨幅多少,在未来一段时间内存会不会达到危险水位。 内存管控方案提供主动和被动通知两种方式获取内存水位状态,实现了各业务层根据手机内存情况实时降级,时效性更强,跟之前服务端降全量降级方案相比,更加灵活,性能更好。   该方案上线后,随着Q2基础服务层和业务线接入,实现OOM降低一半的收益,并且业务层接入成本很低,后续会推动更多内存大户和OOM频发的页面接入。感谢各位阅读至此,如有问题请不吝指正。   八.
  参考链接   [1] 、OOM探究:XNU 内存状态管理: https://www.jianshu.com/p/4458700a8ba8   [2]、XNU源码: https://opensource.apple.com/source/xnu/   [3]、《深入解析Mac OS X & iOS操作系统》   [4]、iOS Out-Of-Memory 原理阐述及方案调研: https://juejin.cn/post/6844903749836603400#heading-7   作者:RichardYang   来源:微信公众号:百度App技术   出处:https://mp.weixin.qq.com/s/dETOGD3NYU2SdZhxGu0SZg

RoboTaxi成本拐点2026年现,出行服务订单将超2600亿美元RoboTaxi(无人驾驶出租车)是基于自动驾驶技术,并能提供出租服务的车辆。日前,特斯拉投资者关系主管马丁维查在高盛科技峰会上表示,ModelX和S是特斯拉的第一代平台,Mode互联网不是法外之地7月21日,国家互联网信息办公室依据相关法律法规,对滴滴全球股份有限公司处人民币80。26亿元罚款,对滴滴全球股份有限公司董事长兼ceo程维总裁柳青各处人民币100万元罚款。从目前新能源汽车充电桩安装困难??苏宁易购帮客3小时解决安装国家双碳战略部署持续推进,带动新能源汽车行业进入高速发展阶段,越来越多的家庭选择购买新能源汽车。数据显示,2022年1月新能源汽车销量迎来开门红,较去年同期增长1。4倍,2月份多家家用扫拖一体机真的实用吗?南京消协发布25款产品比较试验结果,给出这些建议视频加载中现代快报讯(通讯员市消萱记者杜雪迎文摄)智能扫拖一体机可以自动清扫地面,受到越来越多家庭的青睐。目前,市场上扫拖一体机品牌繁多,但在日常使用中很多消费者反映扫拖一体机不实广州互联网法院成立4周年,打造粤港澳大湾区互联网司法引擎据商务部统计,至2021年12月,我国网民规模达10。32亿,网络购物用户规模达8。42亿,网上外卖用户规模达5。44亿。数字经济新业态新模式竞相涌现,数字经济总量跃居世界第二,成今年河南高速服务区充电桩100覆盖,上汽新能源乘势而上不断提速伴随着新能源汽车产品的日臻成熟,消费者对于新能源汽车接受度越来越高,新能源汽车已由政策导向转变成消费市场导向,随着充电桩等基础设施的普及,新能源汽车的渗透率有望进一步提高。为进一步丁刚iPhone转到印度生产对中国可能是好事来源丁刚看世界苹果的代工制造商已开始在印度生产iPhone14了。美欧分析师普遍认为,这是莫迪政府为追赶中国,使印度成为第二个世界工厂而迈出的重要一步。表面看来,此事对中国不利,但孩子被诊断双相,父母如何帮助孩子建立真正自信,加快康复?本文字数约6844字阅读时间约8分钟本文章节01他从小爱学习,但原生家庭有很多隐患02身为学霸的他,为什么突然变得厌学?03父母做到这2点,引导孩子建立真正自信04真正亲密的亲子关姓席的女孩子叫什么名字好听好的名字陪伴我们一生有着深远的影响,吉利的名字自然能够带来好运气,而姓名学的选择却是一门高深的学问,名字不仅要好记好听,更要能够符合孩子一生发展的气运,作为陪伴我们一生的符号,不管巩固孩子积极的重要经历马丁塞里格曼这样说作为父母及教师,必须时时想到多次成功很可能会使孩子习得乐观,你应该尽力帮助孩子,在成功之后继续成功。正确的教导,可支持并维持孩子的乐观,同时较积极的重要经历也会使王菲的女儿16岁了,叛逆又性感胆量不输妈妈,网友风尘味好重2006年,李嫣出生时就已经轰动全国,首先是因为她是李亚鹏和王菲的孩子,还有一个重要的原因,她是天生唇腭裂,也就是兔唇。王菲和李亚鹏都是俊男靓女,他们的女儿却有着先天不足,一时轰动
快收藏!中秋出行这些信息对你或有用交警提醒假期市民将以短途出行为主热门景区车流量较大本报讯(记者张佳)9月8日,记者从市公安局交警支队了解到,结合对交通路况大数据分析,西安公安交警预测,节日期间西安市民出行将以短途学界泰斗,人世楷模今天我们来到的是被誉为五四元老中国新文化运动之父学界泰斗的蔡元培先生的故居。在前一天的傍晚,我们吃完晚饭后就先来到了蔡元培故居,我们为了方便第二天的拍摄便先行来到这里踩点。虽然没能夏季的阿尔山,有多精彩?大兴安岭这片名为极寒之地的广袤山林以其古老神秘的姿态吸引着古往今来无数人的目光比起我国西部的雪山大兴安岭似乎并无冲天之势山地与云海静静交错数万座山峰如波浪般连绵起伏这是大兴安岭最常千年复州古城魅力非遗文化央视网消息在深入推进新型城镇化建设的同时,瓦房店也更加注重历史文脉的传承,位于城区中西部的复州古城就是这座县城的发源地。它始于千年前的辽代,城内历史遗迹保存完整,更有复州皮影大鼓和深度学习库SynapseMLfor。NET发布0。1版本2021年11月微软开源一款简单的多语言的大规模并行的机器学习库SynapseML(以前称为MMLSpark),以帮助开发人员简化机器学习管道的创建。具体参见1微软深度学习库Syn推荐一个好用的开源电商系统,支持H5小程序公众号开源精选是我们分享GithubGitee等开源社区中优质项目的栏目,包括技术学习实用与各种有趣的内容。本期推荐的是一个基于Yii2Vue2。0uniapp框架研发的单商户商城系统开全球新兴市场移动应用报告易观分析海外新兴市场快速发展,出海已成为中资企业发展的核心策略之一。易观分析联合Pangle共同发布的全球新兴市场移动应用报告关注全球非游移动互联网市场。从实用工具社交通讯信息资讯河南首条无人驾驶线路开通倒计时,背后是神奇的信号系统河南日报客户端记者宋敏9月8日,搭载卡斯柯信号系统的郑州机场至许昌市域铁路正式空载试运行,标志着河南省乃至中原地区首条全自动无人驾驶轨道交通线路迎来开通倒计时,距离载客试运营目标又力帆科技借力战投新能源车销量涨180倍上半年营收增逾80挑战全年倍增可期长江商报消息长江商报记者李启光缓过一口气后,力帆科技开始爆发。9月5日晚间,力帆科技(601777。SH)公告称,公司前8月汽车销量达2。73万辆,同比增长24068。14。其中,郭台铭傻眼了!苹果带着富士康去印度建厂,没想到打脸来得这么快作者笔动科技巅峰时期的华为到底有多强大?2019年华为和当时的子品牌荣耀,加起来一起占据了国内市场56的市场份额,在中国横行霸道多年的苹果,市场一度萎缩至8。凭借着麒麟芯片的优秀表iPhone14Pro最抢手!苹果iPhone14系列预约人数超200万今天20点,iPhone14系列四款机型在各大电商平台开启预购,起售价为5999元。当前,iPhone14系列在苹果京东自营旗舰店接受预约,其中iPhone14Pro最受欢迎,预约