如何在进程启动时降低IOKit保留的内存量?

11

我是一名开发人员,正在开发一款非常大、占用内存较多的32位应用程序。对我们来说,虚拟地址空间(内存)不足是一个问题。在调查最近的一些问题时,我注意到IOKit保留了一大块内存(512MB)。这段内存没有被分配,只是被保留。进一步的调查显示,大多数应用程序(如Safari,iTunes等)也都保留了这块内存。它似乎一直没有被分配。我正在使用vmmap进行测试。例如,这是一个使用XCode默认模板创建的Cocoa应用程序:

REGION TYPE                      VIRTUAL
===========                      =======
CG backing stores                  1008K
CG image                              4K
CG raster data                       64K
CG shared images                   2252K
Carbon                             7264K
CoreGraphics                         16K
IOKit (reserved)                  512.0M        reserved VM address space (unallocated)
MALLOC                             59.0M        see MALLOC ZONE table below
MALLOC guard page                    48K
MALLOC metadata                     348K
Memory tag=242                       12K
STACK GUARD                        56.0M
Stack                              8712K
VM_ALLOCATE                        16.2M
__DATA                             8296K
__IMAGE                            1240K
__LINKEDIT                         31.5M
__TEXT                             76.7M
__UNICODE                           536K
mapped file                        27.4M
shared memory                      1320K
===========                      =======
TOTAL                             809.2M
TOTAL, minus reserved VM space    297.2M

有什么我可以做的来减少或消除那个内存池吗?我们的应用程序非常需要那512MB内存!!!

编辑:我进行了更多的研究,发现这块内存是视频卡帧缓冲区映射到用户空间中。所以更准确的问题是,是否有任何方法限制帧缓冲区占用如此大的用户模式虚拟地址空间?

编辑:进行了进一步的测试,并发现需要更改的关键是IOFBMemorySize。如果执行此命令,则会显示:

ioreg -l | grep IOFBMemorySize

或者您可以在IORegistryExplorer中查看它。尽管我尝试添加到ATIFramebuffer.kext的Info.plist中,但我未能更改该值。我尝试编写一个调用IOConnectSetCFProperty的程序,但它返回kIOReturnUnsupported。

编辑:经过更多的研究,似乎这个IOFBMemorySize键很可能是只读的,仅报告视频卡上可用内存的数量。在CoreGraphics的Configuration.plist中有一些有趣的值,但似乎没有一个能影响内存分配(即使在重启后也是如此)。

3个回答

2
我认为你的看法有些偏颇。
A) IOKit并没有占用512MB的内存来作为帧缓冲区。
B) 在你所贴表格中,它指出保留的VM地址空间(未分配),因此很可能是将驱动器内存映射为虚拟内存空间。
C) 如果你运行的应用程序内存不足,你需要重新结构化它,检查分配和泄漏情况,并在必要时进行缓存和延迟获取。

A) 它正在获取512MB的虚拟地址空间,这取决于帧缓冲区的大小。 B) 是的,虚拟地址空间。其中32位应用程序有4GB。 C) 并没有真正回答这个问题。 - pj4533
可用地址的数量并不重要,可用内存才是关键。仅仅因为你可以数到一个数字,并不意味着你拥有那么多位。 - Grady Player
嗯......不太确定我理解你的意思,但可用地址数量(32位与64位)绝对很重要。事实是,32位任务有(大约)4GB的虚拟地址空间。一旦使用完毕,内存分配就会失败。IOKit为视频卡帧缓冲区保留了512MB的虚拟地址空间,我想知道如何将其降低到更小的数量。 - pj4533
编译为64位并不总是可行的选择。例如,Quicktime不支持64位... - kent
我不确定你想做什么,但改变系统可能不是一个答案,你可以尝试使用 mmap 并在实质上分配到另一个地址空间,使用物理地址扩展。我会在此时重申... 你需要做一些不同的事情,缓存和提取,或者在某个地方进行优化。 - Grady Player
显示剩余3条评论

0

a. 你尝试在较弱的显卡上运行过吗?这样可能只会分配128fb? 视频卡的硬件设置呢?

b. 使用代码注入来取消内存分配...

假设这是您的私人应用程序,它不使用framebuff等等
这显然不是单行更改,但您可以更改代码以分配较小的缓冲区,或者失败分配,或允许分配然后释放它(并在程序关闭期间反转此操作),等等

我敢打赌这可以以稳定的方式完成


由于每个OSX应用程序都表现出这种行为,我尝试检查在其他机器上运行不同视频卡的进程。是的,保留的内存量是不同的(它被保留了,但显然没有分配)。我寻找硬件设置,深入挖掘设置,但没有发现任何用户可设置的内容。在与苹果公司讨论此问题后,似乎完全由视频驱动程序控制。我可以钩住调用,但苹果公司建议不要这样做(显然)。 - pj4533
好的,这真的很极端...但你听起来有一半能力。 - YAZR

0

诚然,这不是对你问题的回答,而是一个关于如何继续的建议...

你写道你正在开发一个非常大的32位应用程序,也许现在是重新考虑可执行架构并将非常大的应用程序分成多个进程的时候了。也许你想将32位特定(QT?)代码打包到一个应用程序中(无论是后台进程还是GUI驱动...),然后将更多的内存密集型和处理导向的部分放入第二个(64位?)应用程序中。有许多种进程间通信方式可供选择,你的应用程序可能会从更并行化的架构中受益。

只是一个想法...祝你好运!

|K<


谢谢……是的,64位是解决这个问题的长期方案。不幸的是,由于客户需求,我们需要支持应用程序的32位分支相当长一段时间。 - pj4533
此外,我一直在想是否有一种方法可以制作一个低级别的Out-of-proc内存分配器。通过使用IPC重写malloc函数并使用另一个(64位)进程中的“内存”来实现自己的实现。虽然这似乎有些牵强,但在大型遗留代码库中实现也很困难。 - pj4533

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接