可调页数据结构

要将数据工作集减至最小,请尝试集中常用数据以及避免对虚拟存储器页面不必要的引用。

特别是:

  • malloc()calloc() 子例程来仅请求实际需要的空间大小。 当实际情况只使用数组的一小部分时,切勿请求然后初始化最大的数组。 当您得到一个新页面用来初始化数组元素时,您实际上是强制 VMM 从别处窃取一个实内存页面。 随后,当拥有该页面的进程尝试再次访问它时,会造成缺页故障。 malloc()calloc() 子例程的差异不仅仅在接口上。
  • 因为 calloc() 子例程将分配的存储器置零,它与每一个分配的页面相关,而 malloc() 子例程只与第一个页面相关。 如果您用 calloc() 子例程分配一大块区域,然后最初只使用一小部分,那么您对系统施加了不必要的负载。 不仅页面必须初始化;如果它们的实内存帧被回收,那么已初始化但从未使用的页面必须写出到调页空间。 这种情况浪费 I/O 和调页空间槽。
  • 大结构(如缓冲区)的链表可以引起类似的问题。 如果您的程序执行大量寻找某个特定密钥的链式跟踪,请考虑保持链接和密钥与数据分离或使用散列表方法来代替。
  • 引用局部性意味着时间上的局限性,而不仅仅是地址空间上。 仅在使用之前初始化数据结构(如果在根本上)。 在重负载系统中,在初始化和使用之间长时间驻留的数据结构有帧被窃取的危险。 然后您的程序就会在开始使用数据结构时发生不必要的缺页故障。
  • 同样,如果早先使用一个大结构,然后与程序剩余部分无关联,它应该会被释放。 使用 free() 子例程来释放由 malloc()calloc() 子例程分配的空间是不够的。 free() 子例程仅仅释放结构占用的地址范围。 要释放实内存和调页空间,也可使用 disclaim() 子例程来放弃空间。 对 disclaim() 的调用应该在调用 free() 之前进行。