使用内存映射文件实现虚拟内存

发布于 2024-12-16 13:15:36 字数 859 浏览 0 评论 0原文

是否可以像这样包装内存映射文件?

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 请求上使用 MapViewOfFileAddr 64 位整数只是内存映射文件中的偏移量。悬而未决的问题是如何分配这些地址 - 我目前保留了我维护的空闲块列表。

Is it possible to wrap up memory mapped files something like this?

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

Since the memory mapped file API functions all take offsets I don't know how to manage the free areas in the memory mapped files. My only idea is to implement some kind of basic memory management (mainting free lists for different block sizes) but I don' t know how efficient this will be.

EDIT: What I really want (as David made clear to me) is this:

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

I need to store continous blocks of bytes (each relatively small) in virtual memory and be able to read them back into memory using a 64-bit adress. Most of the time access is read-only. If a write is necessary I would just use FreeMem followed by AllocMem since the size will be different anyway.

I want a wrapper for a memory mapped file with this interface. Internally it has a handle to a memory mapped files and uses MapViewOfFile on each ReadMem request. The Addr 64-bit integers are just offsets into the memory mapped file. The open question is how to assign those adresses - I currently keep a list of free blocks that I maintain.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧梦荧光笔 2024-12-23 13:15:36
  1. 内部有一个内存映射文件的句柄,并在每个 ReadMem 请求上使用 MapViewOfFile”,恕我直言,这只是浪费 CPU 资源。

  2. 值得一提的是,您的 GetMem / FreeMem 要求将无法突破 3/4 GB 的障碍。由于在调用 FreeMem 之前所有分配的内存都将映射到内存中,因此您将缺乏内存空间,就像常规的 Delphi 内存管理器一样。您能做的最好的事情就是依靠 FastMM4,并更改您的程序以减少其内存使用。

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

您希望能够为您的应用程序分配超过 3/4 GB 的数据。您可以在我们的 SynBigTable 开源单元中实现此类功能。这是一个快速、轻量的纯 Delphi 中的 NoSQL 解决方案。

它能够创建任意大小的文件(仅限 64 位),然后根据请求将每个记录的内容映射到内存中。如果可能的话,它将使用文件的内存映射。您可以使用 TSynBigTable 方法非常直接地实现您的接口:ReadMem=Get、AllocMem=Add、FreeMem=Delete。 ID 将是类似指针 的值,并且将使用RawByteString 而不是TBytes

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

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

  1. Your proposal that "Internally it has a handle to a memory mapped files and uses MapViewOfFile on each ReadMem request" will be just a waste of CPU resource, IMHO.

  2. It is worth saying that your GetMem / FreeMem requirement won't be able to break the 3/4 GB barrier. Since all allocated memory will be mapped into memory until a call to FreeMem, you'll be short of memory space, just as with the regular Delphi memory manager. The best you can do is to rely of FastMM4, and change your program to reduce its memory use.

  3. IMHO you'll have to change/update your specification. For instance, your "updated" question sounds just like a regular storage problem.

What you want is to be able to allocate more than 3/4 GB of data for your application. You have a working implementation of such a feature in our SynBigTable open source unit. This is a fast and light NoSQL solution in pure Delphi.

It is able to create a file of any size (only 64 bit limited), then will map the content of each record into memory, on request. It will use a memory mapping of the file, if possible. You can implement your interface very directly with TSynBigTable methods: ReadMem=Get, AllocMem=Add, FreeMem=Delete. The IDs will be your pointer-like values, and RawByteString will be used instead of TBytes.

You can access any block of data using an integer ID, or a string ID, or even use a sophisticated field layout (inside the record, or as in-memory metadata - including indexes and fast search).

Or rely on a regular embedded SQL database. For instance, SQLite3 is very good at handling BLOB fields, and is able to store huge amount of data. With a simple in-memory caching mechanism for most used records, it could be a powerful solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文