VirtualAlloc()的_set_new_handler等价?

问题描述 投票:0回答:1

我有一个用于处理大型数据集的数据结构。它本质上充当磁盘数据的“视图”,根据请求从磁盘加载数据;它将尝试尽可能多地在内存中保存数据,以便在下次访问时,不必从磁盘读取数据。当它检测到内存不足时,它会对引用计数为0的数据块执行“清理扫描”。它使用_set_new_handler()设置一个函数,当某些代码在某处尝试malloc()内存但是可以调用此清理时“T。这样,数据结构可以消耗尽可能多的内存,但是当其他人需要一些内存时仍然会“退避”。

现在我遇到的问题是没有使用malloc()(或new())分配一些内存。我第一次开始在调用CreateDIBSection()时看到它,我认为这是因为这个函数直接使用VirtualAlloc()。因此,当分配失败时,不会调用新的处理程序,VirtualAlloc只会失败。 (我也有其他情况也有相同的情况,但是那些我可以解决;所以CreateDIBSection()一个是我的问题的主要“演示案例”;但是使用该特定API的工作不会解决我的一般问题)

所以我的问题是 - 是否有相当于VirtualAlloc()的_set_new_handler(),或VirtualAlloc()失败时通知的另一种方式,以便我可以调用我的'清理内存'功能并再次尝试分配?或者,有没有办法拦截VirtualAlloc()调用,以便我可以检查每个分配的内存可用性,并在必要时进行清理?谢谢。

c++ windows winapi
1个回答
1
投票

“内存”不应被视为基于现代虚拟内存的操作系统上的RAM - 它只是一个可由页面文件或其他映射文件视图支持的保留地址范围。内存根据操作系统的要求分页进出RAM,但实际上应该被认为是磁盘而不是RAM分配。

在尝试构建用户模式内存“缓存”时必须注意确保将其考虑在内,因为天真的尝试将导致净性能损失,因为RAM中实际上没有额外的缓存,并且将无需额外的页面文件分配出。

考虑到这一点,我可以建议:

  • 使用MapViewOfFile(和相关API)创建文件“视图”。这为操作系统提供了最佳提示,即您正在查看的文件将根据需要从其自己的字节直接分页到RAM中,并确保您没有从源文件到页面文件的浪费副本和字节重复。
  • 如果您无法重建为64位应用程序,请在应用程序上使用/ LARGE_ADDRESS_AWARE链接器开关以获得额外2GB的潜在VM分配。
  • 确定您的分配的一些可配置限制:有关其他应用程序如何处理此问题的示例,请参阅Java运行时-Xmx标志。
  • 您还可以使用Address Windowing Extensions来管理从32位应用程序访问“大型”分配。
  • 或者考虑使用加载文件的64位合作伙伴应用程序,然后使用Shared File Sections管理共享窗口到64位应用程序所做的分配。

实际上我认为使用文件映射来创建文件的视图(或多个视图)将是最简单的实现,并提供合理的(如果不是最佳性能) - 即使视图未映射到您的32位进程中并不意味着64位底层OS不能或不会将这些字节保存在其文件IO缓存中的RAM中。

© www.soinside.com 2019 - 2024. All rights reserved.