V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
BroSaltedFish
V2EX  ›  程序员

请教各位大佬, IOS 系统开发 APP 如何避免由于内存过大被系统强制杀死?

  •  
  •   BroSaltedFish · 2022-03-31 11:12:56 +08:00 · 3998 次点击
    这是一个创建于 960 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题。

    39 条回复    2022-04-02 11:22:54 +08:00
    fengjianxinghun
        1
    fengjianxinghun  
       2022-03-31 11:16:48 +08:00
    不要用那么多内存。。。都有原生写,手动管理内存,精确到每一个字节分配
    KouYiGuo
        2
    KouYiGuo  
       2022-03-31 11:21:04 +08:00
    分析一下内存瓶颈,针对性优化。
    BroSaltedFish
        3
    BroSaltedFish  
    OP
       2022-03-31 11:25:18 +08:00
    @fengjianxinghun 感谢回复。
    分配内存是 C++管理的内存池,主要消耗的也是 C++管理的这部分,由于是处理图形相关的内存确实大,也没法再省了。除了省内存还有其他方法吗?
    nicevar
        4
    nicevar  
       2022-03-31 11:26:27 +08:00
    管理好内存,及时释放资源,如果不是超大型 APP ,基本上不会占用太多内存的,总体感觉自动内存管理的语言占主流之后之后,大多数程序员没有良好的内存管理意识了,包括大厂的 APP ,最近的抖音安卓版本内存泄漏的厉害,频繁 GC 卡得半死,闲鱼这种万年内存泄漏大户就更不用说了。
    fengjianxinghun
        5
    fengjianxinghun  
       2022-03-31 11:28:53 +08:00
    @BroSaltedFish 没有,能省肯定能继续省,少占内存才是唯一的真正的解决问题的办法。
    BroSaltedFish
        6
    BroSaltedFish  
    OP
       2022-03-31 11:31:39 +08:00
    @KouYiGuo 感谢回复。
    内存的优化也一直再做,目前也是到达了省无可省的地步了。。。
    除了优化内存,还有其他方法吗?
    BroSaltedFish
        7
    BroSaltedFish  
    OP
       2022-03-31 11:40:13 +08:00
    @nicevar 感谢回复。
    主要消耗内存的不是 Objective-C ,基本不会超过 400MB
    打开的是 CAD 图纸,内存消耗主要集中对图纸这块,而且图纸这里的内存管理是由 C++写的,基本随用随释放,也没有内存泄漏的问题。主要消耗的还是对图纸的处理。
    BroSaltedFish
        8
    BroSaltedFish  
    OP
       2022-03-31 11:41:23 +08:00
    @fengjianxinghun 唉,内存优化不能停,不能停啊。。。
    xwayway
        9
    xwayway  
       2022-03-31 11:47:02 +08:00
    不懂,但是你们需求就是在 ios 打开 cad 图纸?只是查看?还是需要编辑,为什么会占用这么多,是打开图纸的引擎本身就占用很多还是图纸过大导致。有没有可能换个小一点的引擎,如果只是查看,有没有可能在服务端转 jpg ,手机端就让他看个 jpg 就行了。不懂 cad 的小白给出的拙见
    nicevar
        10
    nicevar  
       2022-03-31 11:49:08 +08:00
    @BroSaltedFish 没有内存泄漏的话,估计你们得换方案了,跟读取大文件一样,不能一下子全部装进内存里面,现在的 iOS 设备配置挺高的了,我们以前用 AutoCAD 2004 的时候电脑还不如现在的手机,当然那时候的 CAD 文件没有现在的复杂,不过可行性应该没什么问题。
    raykle
        11
    raykle  
       2022-03-31 11:58:54 +08:00
    我不相信已经省无可省了 /doge

    比如打开 CAD 图纸,图纸过大的话,有使用瓦片方式加载吗?
    BeyondBouds
        12
    BeyondBouds  
       2022-03-31 12:04:14 +08:00
    类似 PS 的 app 怎么省内存?产品要求用户导入的图片必须原图加载编辑.....一般用户也还好,5000x5000 的也还可以,碰见专业的整个 10000x10000 的,真的崩溃....
    DingSoung
        13
    DingSoung  
       2022-03-31 12:08:20 +08:00 via iPhone
    分块夹在
    内存映射
    Building
        14
    Building  
       2022-03-31 12:37:21 +08:00 via iPhone
    @BeyondBouds 无解,资源太大就是会杀,除非自己实现字节流读取图片分区加载,一顿映射下来等于自己控制了内存……太累
    icyalala
        15
    icyalala  
       2022-03-31 13:05:21 +08:00
    一次不要分配过大内存,分成小块分配和使用,实时监控 memory warning 及时释放内存。
    再就是用磁盘来顶一下,临时不需要的数据存下来需要时再解码出来,或者 mmap 。慢就慢些,优先保证不崩。
    其他没有什么太好的手段,就是想办法省内存。
    BroSaltedFish
        16
    BroSaltedFish  
    OP
       2022-03-31 13:05:53 +08:00
    @xwayway 感谢回复。
    需求就是在 IOS 上打开 cad 图纸,需要编辑,图纸引擎本身确实也会占用很多内存,主要还是看图纸,基本 30MB 以上的图纸打开就很有可能被杀死。换引擎基本不可能。。。
    @nicevar 目前我们尝试过,加载核心数据,外围数据按需加载的方式,测试效果因图纸差异效果不等,不过感觉还是得从这方面下手。。。
    @raykle 感谢回复。
    老兄说得对,省无可省是以我现在的能力来看确实没法子了。。。瓦片方式加载我大概了解下是用在地图、图片显示上,我们这还不一样,需要从数据转换成图像,在未读取数据前并不知道位置,不过估计还是得采用局部加载技术手段。
    @BeyondBouds 感谢回复。
    老兄的问题和我一样啊,确实跟用户的 文件有很大关系,内存大也只能硬着头皮优化啊。。。
    @DingSoung 感谢回复。
    文件本身不大,大多数处于 50MB 以内,主要是处理读取文件生成数据过程中的内存问题
    mjawp
        17
    mjawp  
       2022-03-31 13:13:56 +08:00
    @BeyondBouds 不是一定要原图的吧。你甚至可以对缩略图修改,最后原图同样操作合成的
    BroSaltedFish
        18
    BroSaltedFish  
    OP
       2022-03-31 13:15:59 +08:00
    @icyalala 感谢回复。
    内存的管理基本没问题,可能磁盘缓存是后续优化的一个方向了。。。。
    xnth97
        19
    xnth97  
       2022-03-31 14:19:20 +08:00   ❤️ 1
    applicationDidReceiveMemoryWarning 应该给你一次机会了...这时候能释放什么释放什么,总比被杀好
    learningman
        21
    learningman  
       2022-03-31 16:08:22 +08:00
    实在放不下了自己实现虚拟内存吧
    lakehylia
        22
    lakehylia  
       2022-03-31 16:14:44 +08:00
    地图的方法咯,一次只加载屏幕那么大的
    BroSaltedFish
        23
    BroSaltedFish  
    OP
       2022-03-31 16:52:42 +08:00
    @xnth97 感谢回复。
    以编辑方式打开的文件这个接口的帮助就有限了,不过还是感谢提供方案。
    @66450146 感谢回复。
    感谢提供,com.apple.developer.kernel.increased-memory-limit 后续试下效果再回复
    @learningman 感谢回复。
    实现虚拟内存个人水平达不到,可能的方案看看缓存到磁盘了。。。。
    @lakehylia 感谢回复。
    地图的方法目前不太适合,因需要读取数据流生成数据才能知道图元所处的位置。。。
    seakingii
        24
    seakingii  
       2022-03-31 17:50:30 +08:00
    你这是要在冰箱里放个大象啊.

    手机的内存总是要有个限制的,不可能你 CAD 源文件 10 个 G 也能强制打开吧.

    除非你的 CAD 引擎设计的很好,能流式分块加载,然后渲染成省内存的格式
    wwbfred
        25
    wwbfred  
       2022-03-31 18:10:06 +08:00
    呃,你这个问题要有办法绕过,国内应用早就群魔乱舞了……
    sadfQED2
        26
    sadfQED2  
       2022-03-31 18:52:32 +08:00 via Android
    打开前预估内存使用量,然后判断用户当前手机内存是否够,如果用户手机内存不够,直接弹窗提示用户升级手机

    这样至少你 app 不会挂
    FrankHB
        27
    FrankHB  
       2022-03-31 19:00:01 +08:00
    @BeyondBouds 你这什么屑产品经理还管那么多?要空间不够用负责帮用户加内存么?
    @learningman 你清楚在说什么么。
    在没有 MMU 或者没有系统特权的情况下实现虚存跟实现个没硬件加速的系统级虚拟机的工作差不多少。(虽然 iOS 不管 ISA 细节横竖都禁止加速了。)
    Innovatino
        28
    Innovatino  
       2022-03-31 19:06:45 +08:00
    @BroSaltedFish
    iOS 上,不需要 30MB 的图片就可能因为爆内存杀死应用。因为 iOS 的图片加载是按像素渲染的,就算是几 k 的一张纯白图片,也可能因为巨大的分辨率导致爆内存。
    如果没办法使用瓦片方式加载,那唯一的方式就是降低分辨率,让渲染出来的图片没有那么多像素。
    这是必然的,是 iOS 原生 api 的必然结果,想使用,就得按照这个基本法来。想绕过,那就只能看看那些正经的引擎了
    learningman
        29
    learningman  
       2022-03-31 19:17:40 +08:00
    @FrankHB #27 C++用 placement new 搞,工作量不会太大的,不过比系统级别慢挺多就是,应用本身也要改造
    VirgilMing
        30
    VirgilMing  
       2022-03-31 22:27:13 +08:00
    在 iOS 上编辑 CAD 怎么看都像是个伪需求……你们的 CAD 引擎是自己写的吗?
    hytaoist
        31
    hytaoist  
       2022-03-31 22:48:11 +08:00
    autoreleasepool ,防止临时内存暴涨尝试下
    debuggeeker
        32
    debuggeeker  
       2022-04-01 09:12:50 +08:00
    @nicevar 说的太对了,现在软件质量太差了,以前 2g 内存也能好好玩手机,现在 8g 还是卡
    nothingistrue
        33
    nothingistrue  
       2022-04-01 09:35:05 +08:00
    说点题外话,好得产品经理,应该引导客户把沙雕需求变成好需求。如楼主的需求,对于客户来说,PAD/PC/MAC/WEB 编辑查看+手机仅查看,是比手机啥都干,更好的工作方式。如果实在要手机也编辑,那么花钱买个好的引擎,是比让上层 APP 做优化,更有效的实现方式。
    BeyondBouds
        34
    BeyondBouds  
       2022-04-01 10:53:42 +08:00
    @mjawp 谢谢回复,可是还是想不明白,在不对原图解码的情况下,怎样把用户的一些操作合成到原图里....
    BroSaltedFish
        35
    BroSaltedFish  
    OP
       2022-04-01 12:57:27 +08:00
    @seakingii 感谢回复。
    并非是打开文件的问题,CAD 文件内部存储的结构是流式存储的,引擎读取文件也是流式分块加载的,内存消耗主要是生成显示数据过程,我们可能还是需要在这方面努力优化了。。
    @wwbfred 感谢回复。
    总会有内存不够的情况,看优化了吧。。。
    @sadfQED2 感谢回复。
    这个真预估不了,可能的还是 上面老兄说的 applicationDidReceiveMemoryWarning 函数内做处理。
    @VirgilMing 感谢回复。
    引擎是公司买的,我们在上面做开发、适配和优化。
    @hytaoist 感谢回复。
    Objective-C 层消耗内存不多,内存消耗主要是 C++层 CAD 引擎加载文件生成显示数据过程,看来还是得在后者方面做优化
    @nothingistrue 感谢回复。
    产品希望全都要。。。。只能硬着头皮上了
    FrankHB
        36
    FrankHB  
       2022-04-01 13:31:14 +08:00
    @learningman 你想少了。虚存是带地址翻译的,没硬件和系统支持下,首先得把访存的寻址都替换掉,原则上需要多出至少一倍指令。这就还是有类似 MPU 之类的硬件中断的情况,纯软件实现你得模拟缺页中断,基本就是把非交换访存全替换为模拟中断例程的函数调用。要实现这个基本得改编译器(从前端把*替换成 builtin 开始,只改后端还不够)。
    直接 placement new 不能改善同时占用的问题。placement new 要求有已经分配好空间随时能用的指针,都没法用 fancy pointer (而且现在标准库的 allocator model 能分配的还要求在地址空间内连续)。
    learningman
        37
    learningman  
       2022-04-01 15:23:09 +08:00
    @FrankHB #36 你想的是系统级别的虚拟内存,用户态无感,我说的是应用内分配之前先做一次替换
    FrankHB
        38
    FrankHB  
       2022-04-02 03:18:22 +08:00
    @learningman 那种一般就不会叫虚拟内存。
    实际能替换的,基本就只限于光栅图缓冲区这种,也不是 placement new ,还要有 swap buffer 的真 IO 。一些看大图的软件就有这种机制,上面也有人提。但看 OP 的描述,加载都已经分块了,到后面显示渲染还不够用,那这个 swap 就不是重新复制缓冲区那么简单,横竖还得改渲染算法在光栅化之前做文章。这就跟虚拟内存更没共同点了。
    learningman
        39
    learningman  
       2022-04-02 11:22:54 +08:00 via Android
    @FrankHB 对,我是这个意思,肯定要 io 的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4527 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 10:03 · PVG 18:03 · LAX 02:03 · JFK 05:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.