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

Posted

技术标签:

【中文标题】如何在进程启动时降低 IOKit 保留的内存量?【英文标题】:How do I lower the amount of memory IOKit reserves at process start up? 【发布时间】:2011-06-27 15:48:55 【问题描述】:

我是一名开发人员,正在开发一个非常大的内存密集型 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 中似乎有一些有趣的值,但它们似乎都不会影响内存分配(即使在重新启动后)。

【问题讨论】:

【参考方案1】:

我认为你看错了。

A) IOKit 没有为帧缓冲区占用 512MB 内存。

B) 它在表中声明您发布了 reserved VM address space (unallocated),因此这可能是映射为虚拟内存空间的驱动器内存。

C) 如果您正在运行的应用程序内存不足,您需要对其进行不同的结构,检查分配和泄漏,并在必要时执行缓存和延迟获取。

【讨论】:

A) 它正在抓取 512mb 的虚拟地址空间,这取决于帧缓冲区的大小。 B)是的虚拟地址空间。其中一个 32bit 应用程序有 4gb。 C) 没有真正回答问题。 有多少地址可用并不重要,有多少内存可用,仅仅因为你能数到一个数字并不意味着你有那么多位。 Ummmm....不确定我理解你在说什么,但有多少地址可用(32 位与 64 位)绝对重要。事实上,32 位任务有(大约)4GB 的虚拟地址空间。一旦使用,内存分配就会失败。 IOKit 为视频卡帧缓冲区保留 512mb 的虚拟地址空间,我想知道如何将其降低到更小的数量。 为什么不直接将应用程序编译为 64 位?自 10.5 以来的所有内容都支持它,它将您的虚拟机提升到 64gig。 developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… 编译为 64 位并不总是一种选择。 Quicktime 不支持 64bit,例如...【参考方案2】:

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

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

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

|K

【讨论】:

谢谢....是的,64 位是这个问题的长期解决方案。不幸的是,由于客户的需要,我们需要在相当长的一段时间内支持我们的应用程序的 32 位分支。 另外,我想知道是否有某种方法可以制作低级别的进程外内存分配器。通过用我自己的实现覆盖 malloc ,该实现使用 IPC 从另一个(64 位)进程获取“内存”。不过似乎总是有些牵强(更不用说在大型遗留代码库中难以实现)。【参考方案3】:

一个。您是否尝试过在较弱的显卡上运行它?那么也许只会分配128fb? 显卡的硬件设置?

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

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

我敢打赌这可以稳定地完成

【讨论】:

由于每个 OSX 应用程序都表现出这种行为,我尝试检查其他机器上的进程,运行不同的显卡。是的,保留的内存量不同。 (它是保留的,但显然没有分配)。我寻找了一个硬件设置,深入研究了 REAL 设置,但没有发现任何用户可设置的内容。在与苹果讨论过这个问题后,它似乎完全由视频驱动程序控制。我想我可以挂断电话,但 Apple 建议不要这样做(显然)。 好吧..这真的很极端......但你听起来很不称职

以上是关于如何在进程启动时降低 IOKit 保留的内存量?的主要内容,如果未能解决你的问题,请参考以下文章

安卓Android的内存管理原理解析

Android进程分类与管理

如何为 IOKit 属性设置临时权利?

僵尸进程

MSI安装的数据持久性

C++。如何获得进程从一开始就分配的最大内存量?