在Mac OS X上,如何在64位进程中中等大小的内存分配失败?

Nik*_*uhe 12 macos 64-bit memory-management nsdata

我正在构建照片书布局应用程序.应用程序经常将JPEG图像解压缩到内存位图缓冲区中.图像的大小限制在100万像素(而它们通常不超过1500万像素).

有时这些缓冲区的内存分配失败:[[NSMutableData alloc] initWithLength:]返回nil.这似乎发生在系统的自由物理内存接近零的情况下.

我的理解在Mac OS X中的虚拟内存系统是在64位进程的分配实际上(原文如此),不能失败.有16个exabyte的地址空间,我试图一次分配最多400兆字节.从理论上讲,我可以分配400亿个缓冲区而不会遇到可用地址空间的硬限制.当然,实际限制会阻止这种情况,因为交换空间受启动卷大小的限制.实际上,我只做了很少的这些分配(少于10个).

我不明白的是,无论物理内存有多低,分配都会失败.我认为 - 只要有交换空间,内存分配就不会失败(因为此时页面甚至没有映射).

该应用程序是垃圾收集.

编辑:

我有时间进一步深入研究这个问题,这是我的发现:

  1. 该问题仅发生在垃圾收集过程中.
  2. 当分配NSMutableData失败时,普通malloc仍然可以成功分配相同数量的内存.
  3. 当整体物理内存接近零(交换即将发生)时,总会发生错误.

我假设NSData用于NSAllocateCollectable执行分配而不是malloc在垃圾收集下运行时.

我的结论是,当物理内存很低时,收集器无法分配大块内存.再一次,我不明白.

nsc*_*idt 9

答案在于libauto的实现.

从OS X 10.6开始,在64位平台上为垃圾收集内存分配了8 Gb的竞技场.对于大型分配(> = 128k)和小型(<2048b)或中型(<128k)分配,此竞技场被削减一半.

因此,对于10.6,你有4Gb的内存可用于垃圾收集内存的大量分配.在10.5上,竞技场的大小为32Gb,但苹果在10.6上将这个大小降低到了8Gb .