首页 > 解决方案 > 为动态数组预留较大的虚拟内存空间,并根据需要映射核心内存

问题描述

我需要一个大型动态数组。我不知道它可以达到的最大大小,但我可以设置一个很大的上限,比如 1 GB。

我知道的动态数组实现,当它们达到最大容量时,分配一个新的更大的缓冲区,将数据复制到它并释放旧的缓冲区。我想避免这种情况,所以我正在考虑保留一大块虚拟内存,并且只在需要时将虚拟内存页面映射到物理内存。除了效率之外,这种方法的一个很好的特点是保证项目的地址永远不会改变。

我正在考虑类似这样的逻辑:

// the memory used by the dynamic array
item_t* buffer = reserve_virtual_memory( 1gigabyte );

size_t len = 0; // how many items the dynamic array contains
size_t pages = 0; // how many virtual memory pages are in use

// computes how many memory pages are needed to store `len` items
size_t needed_pages( size_t len ) {
  return ( sizeof(item_t)*len - 1 ) / page_size + 1;
}

item_t* new_item() {
  len += 1;
  if( needed_pages(len) != pages ) {
    ASSERT( needed_pages(len) == pages+1 );
    pages += 1;
    map_memory_page( buffer + pages*page_size );
  }
}

void pop_item() {
  len -= 1;
  if( needed_pages(len) != pages ) {
    ASSERT( needed_pages(len) == pages-1 );
    release_memory_page( buffer + pages*page_size );
    pages -= 1;
  }
}

我应该能够在 Linux 上使用mmapand来实现这个逻辑madvise

我在想:

  1. 将这种设计用于大型动态数组有什么缺点吗?

  2. 这是一个常见的解决方案吗?它有名字吗?有没有已经实现它的库?

  3. 它可以在每个/大多数平台上实现吗?包括WebAssembly之类的虚拟机?

标签: c++cmemorymmapdynamic-arrays

解决方案


  1. 一个潜在的缺点是您可能更容易耗尽进程的地址空间。在您的示例中,您保留了 1 GiB 的虚拟内存(即使数组为空),这将是典型 32 位 Windows 安装上进程的 2 GiB 私有地址空间的一半。这只会为其他数据留下 1 GiB 的内存。这对于现在的大多数系统来说都不是问题,因为它们通常是 64 位系统,但如果您仍想支持旧的或更小的系统,这可能是一个问题。
  2. 我在网上搜索这个想法大约 30 分钟时发现了你的问题。我会说这似乎不是一个常见的解决方案。

    需求分页内存过度使用似乎与这个想法有些相关,因为它们允许分配比实际驻留在物理内存中更多的内存。这两种都是常用的。

推荐阅读