1

是否可以将内存映射文件包装起来?使用内存映射文件实现虚拟内存

TVirtualMemoryManager = class 
public 
    function AllocMem (Size : Integer) : Pointer; 
    procedure FreeMem (Ptr : Pointer); 
end; 

由于内存映射文件API函数全部取偏移量,我不知道如何管理内存映射文件中的空闲区域。我唯一的想法是实现某种基本的内存管理(维护不同块大小的免费列表),但我不知道这将是多么有效。

编辑:我真的想(大卫清楚地向我)是这样的:

IVirtualMemory = interface 
    function ReadMem (Addr : Int64) : TBytes; 
    function AllocateMem (Data : TBytes) : Int64; 
    procedure FreeMem (Addr : Int64); 
end; 

我需要的字节连续块(每个比较小)存储在虚拟内存中,并能够使用64位地址将它们读回到内存中。大部分时间访问是只读的。如果需要写入,我将仅使用FreeMem,然后再使用AllocMem,因为无论如何,大小都会有所不同。

我要为内存的封装映射文件与该接口。它在内部具有内存映射文件的句柄,并在每个ReadMem请求上使用MapViewOfFile。 64位整数只是内存映射文件的偏移量。一个悬而未决的问题是如何分配这些地址 - 我目前保留了我维护的空闲块列表。

+1

“虚拟内存”是什么意思?系统已经为你做了。 –

+0

我想绕过2/3/4 GB的内存限制,并希望由文件(本例中为页面文件)支持的虚拟内存。 – jpfollenius

+0

在这种情况下,您需要与此不同的界面。你需要一个能够让你通过地址空间限制的接口,但这不是。 –

回答

2
  1. 你的建议,即“内部,它有一个句柄内存映射文件,并在每个ReadMem要求使用MapViewOfFile”将只是一个CPU资源的浪费,恕我直言。

  2. 值得一说的是你的GetMem/FreeMem要求将无法突破3/4 GB屏障。由于所有分配的内存都会映射到内存中,直到调用FreeMem,所以与普通的Delphi内存管理器一样,内存空间不足。你能做的最好的就是依靠FastMM4,并改变你的程序来减少它的内存使用。

  3. 恕我直言,你必须改变/更新你的规范。例如,您的“更新”问题听起来就像是一个常规的存储问题。

你想要的是能够分配超过3/4 GB数据的应用程序。您在我们的SynBigTable开放源代码单元中具有这种功能的工作实现。这是纯德尔福公司的一个快速和轻量级的解决方案NoSQL

它能够创建任何大小的文件(仅64位有限),然后将每个记录的内容映射到存储器中,在请求。如果可能,它将使用文件的内存映射。您可以使用TSynBigTable方法直接实现您的界面:ReadMem=Get, AllocMem=Add, FreeMem=Delete。这些ID将是您的pointer类似的值,将使用RawByteString而不是TBytes

可以访问使用整数ID,或一个字符串ID数据的任何块,或甚至使用一个复杂的场布局(该记录内,或如在内存中的元数据 - 包括索引和快速搜索)。

还是依靠常规的嵌入式SQL数据库上。例如,SQLite3非常擅长处理BLOB字段,并且能够存储大量的数据。通过简单的内存缓存机制来处理大多数使用过的记录,它可能是一个强大的解决方案。

+0

这个想法大概是当内存不再需要时取消映射。 –

+0

@DavidHeffernan这就是为什么即使在问题中的新的ReadMem方法接口是不够的。使用存储库将依赖于请求分配内存。正如我的第一点所言,映射和取消映射会产生成本 - 这些API并非专为小块内存而设计的,例如[最小x86分页为4 KB](http://en.wikipedia.org/wiki/Page_ (computer_memory)),每个内存映射都需要额外的内存(Windows句柄,额外的内存结构......)。 –

+0

@DavidHeffernan这个问题的问题是,技术设计已经修复 - 恕我直言,是错误的。存储器映射不可用于OP提议的内容。这不会有效。因此,我建议进入另一个方向来解决原始的软件需求:处理大量的存储器块,而不需要32位程序的3/4 GB内存限制。这需要一个常规的存储引擎(NoSQL或SQL)。依靠现有的库有时是一个好主意和节省时间。 –