如何避免iOS中的堆碎片

如何避免iOS中的堆碎片,ios,objective-c,heap-fragmentation,objectpool,Ios,Objective C,Heap Fragmentation,Objectpool,我们的应用程序在运行时会创建很多小对象。它主要归结为自动释放的NSString和NSNumber对象。由于应用程序设计为在后台“24/7”运行,堆碎片成为一个大问题 在没有对程序进行完整重组的情况下,有哪些技术可以避免这种情况 我在想: -对象池,该对象池将在最终发布后将对象返回到池中,但此时对象需要是可变的。(NSMuttableString本身会导致堆碎片吗?) 其他人如何处理这些问题 编辑:这就是我对内存碎片产生怀疑的原因。查看rpages和[vm PageShorth] eInc

我们的应用程序在运行时会创建很多小对象。它主要归结为自动释放的NSString和NSNumber对象。由于应用程序设计为在后台“24/7”运行,堆碎片成为一个大问题

在没有对程序进行完整重组的情况下,有哪些技术可以避免这种情况

我在想: -对象池,该对象池将在最终发布后将对象返回到池中,但此时对象需要是可变的。(NSMuttableString本身会导致堆碎片吗?)

其他人如何处理这些问题

编辑:这就是我对内存碎片产生怀疑的原因。查看rpages和[vm PageShorth]

    eIncident Identifier: 81E87769-8E16-4439-AFFA-6D077E01E5ED
CrashReporter Key:   96235931c31c6b92a16f5c1b1e4cb363a3d18a67
Hardware Model:      iPhone4,1
OS Version:          iPhone OS 7.0.4 (11B554a)
Kernel Version:      Darwin Kernel Version 14.0.0: Fri Sep 27 23:00:48 PDT 2013; root:xnu-2423.3.12~1/RELEASE_ARM_S5L8940X
Date:                2013-12-13 22:43:36 -0800
Time since snapshot: 1582 ms

Free pages:                              1105
Active pages:                            3668
Inactive pages:                          2035
Speculative pages:                       46
Throttled pages:                         100120
Purgeable pages:                         0
Wired pages:                             22159
File-backed pages:                       5400
Anonymous pages:                         349
Compressions:                            0
Decompressions:                          0
Compressor Size:                         0
Uncompressed Pages in Compressor:        0
Largest process:   Argus

Processes
     Name                    <UUID>                       rpages       recent_max   fds      [reason]          (state)

        Facebook <979b9707d85a31df94b986d91d8c3ce7>         2368             2368  100   [vm-pageshortage]  (resume)
       MobileSMS <339505ebbbc4301e87379b095a38ba13>         1448             1448  100   [vm-pageshortage]  (background)
      MobileMail <b3574f4bded1315cb2e50e5de205be48>         1575             1575  100   [vm-pageshortage]  (resume) (continuous)
            tccd <1fea8c5a71943151b5cd304c7eb0fd8c>          198              198  100   [vm-pageshortage]  (daemon)
             kbd <be2d64e41bf43e48a09a23fb129eb0b4>          739              739  100   [vm-pageshortage]  (daemon)
      librariand <15fb21b24e823e158caed9f9e9d8b87a>          299              299  100   [vm-pageshortage]  (daemon)
     MobilePhone <10e2242652423ae28f278a807a0d6384>         1852             1852  200   [vm-pageshortage]  (continuous)
       CVMServer <f26614f7fef63e2faa518272f0fc600a>           96               96  200   [vm-pageshortage]  (daemon)
           Argus <d214b453a3453121a8495d5c8eba80fd>        51299            51299  100   [vm-pageshortage]  (location) (frontmost) (resume)
identityservices <18cc20db2e4739a782cc8e38e03eff52>          398              398  100                      (daemon)
           wifid <a5cf99e5a0f032a69bc2f65050b44291>          652              652   25                      (daemon)
         syslogd <6539f4cf4dcf34daadf1d99991926680>          140              140   50                      (daemon)
          powerd <0a253ac2a99236809422214be1700bc0>          126              126  100                      (daemon)
             vmd <93cffd22b64631afa08a42f6a85e1f33>          297              297  100                      (daemon)
         imagent <bef102e1faef39209926fb25f428a71e>          438              438  100                      (daemon)
eIncident标识符:81E87769-8E16-4439-AFFA-6D077E01E5ED
CrashReporter钥匙:96235931c31c6b92a16f5c1b1e4cb363a3d18a67
硬件型号:iPhone4,1
操作系统版本:iPhone操作系统7.0.4(11B554a)
内核版本:达尔文内核版本14.0.0:Fri Sep 27 23:00:48 PDT 2013;根目录:xnu-2423.3.12~1/RELEASE_ARM_S5L8940X
日期:2013-12-13 22:43:36-0800
自快照以来的时间:1582毫秒
免费网页:1105
活动网页:3668
非活动页面:2035
投机性页码:46
限制页数:100120
可购买页面:0
有线网页:22159
文件备份页:5400
匿名网页:349
压缩:0
解压缩:0
压缩机尺寸:0
压缩器中未压缩的页:0
最大的进程:阿古斯
过程
名称rpages最近的最大fds[原因](状态)
Facebook 2368 2368 100[虚拟机页面短缺](简历)
MobileSMS 1448 1448 100[虚拟机缺页](后台)
手机邮箱15751575100[vm PageShorth](简历)(连续)
tccd 198 198 100[vm PageShorth](守护进程)
kbd 739 739 100[vm PageShorth](守护进程)
图书管理员299 299 100[vm PageShorth](守护进程)
移动电话1852 1852 200[虚拟机缺页](连续)
CVMServer 96 96 200[vm PageShorth](守护进程)
Argus 51299 51299 100[虚拟机页面短缺](位置)(最前面)(简历)
identityservices 398 398 100(守护进程)
wifid 652 652 25(守护进程)
syslogd 140 50(守护进程)
powerd 126 100(守护进程)
vmd 297 297 100(守护进程)
imagent 438 438 100(守护进程)

处理此问题的一种方法是找到导致碎片问题的“90%”罪魁祸首。您的代码中可能存在导致瑞士奶酪效应的病理状况

初步行动 不言而喻,您应该首先说服自己,您的高页面使用率是由于碎片,而不是由于内存泄漏。:-)

如果您还没有这样做过,那么在Xcode中使用“Instruments”应用程序是在iOS模拟器中观看您的程序分配内存的绝佳方式。使用分配泄漏工具,您可以记录代码执行的每个对象分配和malloc(),以及方便的时间戳。(如果ARC没有像它应该的那样释放内存,工具将免费显示对象贴图中的循环。)

通常,这些工具会跟踪仍在使用的内存。您可以在“分配配置”窗格中选择“创建和销毁”选项,以跟踪所有内容,这些内容可以在摘要信息正上方的弹出窗口中查看

还有一个VM页面分配工具,它可能会为您的问题提供一些帮助

可能的补救办法 一旦确定了罪魁祸首,就可以重新构造代码以防止出现病理状况。或者,如果重构成本太高,您可以通过重用内存来减轻这种情况的影响

通常,当分析显示对象分配和解除分配正在导致漏洞,或者某个特定对象正在以惊人的频率分配/解除分配时,我会将违规者放入对象“池”

这可以像将对象存储在NSMutableArray中并根据需要推送和弹出它们一样简单

当然,您可能需要一些更复杂的东西,在获取对象时初始化对象,使用就绪对象初始化池,并在池为空或运行不足时使用对象自动重新填充。在iOS中,如果收集的对象太多或收到内存不足警告,您还需要修剪池

很好的一点是,这可以是非常通用的代码,您可以永远重复使用。:-)

旁注
您提到了不希望使对象可变的问题。在某些情况下(如NSString),如果您(提前)知道需要对字符串执行的空间要求和操作,它可以帮助提高效率。这样,您可以提前告诉它您需要多少空间,并对字符串“就地”进行操作,从而减少分配开销。(NSString在引擎盖下所做的是另一篇文章。:-

我只是好奇:您是如何检测/测量堆碎片的?它到底导致了什么问题?您打算如何控制这些类的内部内存分配?iOS扼杀了应用程序和bunch