我有一个用于处理大型数据集的数据结构。它实质上是磁盘数据的“视图”,根据请求从磁盘加载数据。它会尝试将尽可能多的数据保留在内存中,以便下次访问时不必从磁盘读取数据。当它检测到内存不足时,将对引用计数为0的数据块进行“清理清除”。它使用_set_new_handler()设置一个函数,当某个地方的某些代码尝试对malloc()进行内存访问但可以没错这样,数据结构可以消耗尽可能多的内存,但是当其他人需要一些内存时仍然会“退缩”。
现在我有一个问题,就是没有使用malloc()(或new())分配一些内存。我首先开始在对CreateDIBSection()的调用中看到它,我认为这是因为此函数直接使用VirtualAlloc()。因此,当分配失败时,不会调用新的处理程序,而VirtualAlloc只会失败。 (我也有其他情况相同的情况,但我可以解决这些情况;因此,CreateDIBSection()是我主要的问题“演示案例”;但是使用该特定的API不能解决我的一般问题)
所以我的问题是-是否有等效于_set_new_handler()的VirtualAlloc(),或在VirtualAlloc()失败时得到通知的另一种方式,以便我可以调用“清理内存”功能并再次尝试分配?另外,是否有一种方法可以拦截VirtualAlloc()调用,以便我可以检查每个分配的内存可用性,并在必要时进行清理?谢谢。
答案 0 :(得分:1)
“内存”不应该表示基于现代虚拟内存的OS上的RAM,它只是保留的地址范围,可以由页面文件或某些其他映射的文件视图支持。操作系统会根据需要将内存分页到RAM中或从RAM中调出,但实际上应该将其视为磁盘而不是RAM分配。
在尝试构建用户模式内存“高速缓存”时,必须小心以确保将其考虑在内,因为幼稚的尝试将导致净性能损失,因为实际上没有多余的缓存在RAM中,并且不必要的额外页面文件分配给翻页和翻页。
考虑到这一点,我可以建议:
使用MapViewOfFile(和相关的API)来创建文件“视图”。这样可以为操作系统提供最佳提示,即您可以根据需要将正在查看的文件直接从其自己的字节直接分页到RAM中,并确保您不会浪费字节并将字节从源文件复制到pagefile中。
如果您无法将其重建为64位应用程序,请使用应用程序上的/ LARGE_ADDRESS_AWARE链接器开关,以获得额外2GB的潜在VM分配。
确定分配的一些可配置限制:有关其他应用程序如何处理此问题的示例,请参见Java运行时-Xmx标志。
您还可以使用Address Windowing Extensions来管理对32位应用程序对“大”分配的访问。
或考虑使用加载文件的64位合作伙伴应用程序,然后使用Shared File Sections来管理64位应用程序分配的共享窗口。
实用上,我认为使用文件映射来创建文件视图(一个或多个视图)将最容易实现,并且即使不是最佳视图,也可以提供合理的性能-即使未在您的32位进程中映射视图也不意味着64位底层操作系统无法或不会在文件IO缓存中将这些字节保留在RAM中。