堆栈+堆+静态内存模型是否可以替代?


9

我见过的所有程序都将其数据存储器组织到一个或多个调用堆栈(通常是固定大小,但有时不是),堆和静态存储器中。最近,线程本地静态存储也已添加到其中。

有没有尝试以根本不同的方式来组织数据存储器布局,例如没有调用堆栈?还是以完成同一件事的另一种方式组织记忆?


取决于您所说的“堆栈”。您可以将调用堆栈帧放入堆中(将它们与指针链接)。这样,您就没有堆栈专用的线性存储区域,但是从概念上讲,您仍然具有调用堆栈。

并取决于您“最近”的意思。我认为线程本地存储与线程一样古老。但是以前可以通过系统调用来访问,而现在更新的语言使您可以直接访问它。
DXM

调用堆栈是必需的,因为过程函数需要知道谁调用了它们,以便它们可以返回结果并继续执行。如果这样做,当前的机制实际上在CPU周期方面非常便宜,并且至少使用x64,几乎所有函数args都通过寄存器传递
James

2
您可能会发现Eric Lippert的帖子,“ 为什么要堆放?” 出于兴趣。他的主要观点是,堆栈提供了一种高效,简单的方式来跟踪内存位置。他在几本比较老的文章中讨论了一种替代方法,Continuation Passing Style
布赖恩

Answers:


8

您可能想退后一步,看看这些现有模型的来源和来源。创建一个进程时,会简单地为其分配一个平坦的存储区,该存储区的索引值从0到N。由于该存储区(在这里谈论RAM)由专用硬件和一些高档的半导体支持,因此它的运行速度非常快,但这不是唯一的一种。诸如硬盘驱动器之类的其他设备本质上是相同的东西,可以通过索引寻址平坦的空间,但是速度要慢许多数量级。

之所以存在“堆”,是因为每个应用程序试图自己管理RAM的使用是不切实际的。追溯到今天,事情就是这样,程序员提前计划了每个RAM位置的确切用途。随着软件变得越来越复杂,有人说,如果我可以只去一些黑匣子说“我需要10个字节,那么就给我”,而不用担心这10个字节在哪里以及如何做的所有复杂细节,那会不会很好来自或如何回收它们。那就是堆,实际上并没有得到更多的基础。

每次创建线程时,都会有一些数据结构(和堆栈),这些数据结构是使用与我刚刚描述的相同的“给定操作”来获取的。堆栈几乎是通用的,因为它非常适合函数调用堆栈框架及其LIFO性质。从理论上讲,每个函数调用和局部变量都可以在堆上分配,但是与更新堆栈指针(x86上的ESP)所需要的一些汇编指令相比,这太昂贵了。

线程本地存储(TLS)也建立在堆的顶部。创建线程时,作为访问堆以为管理结构分配内存的一部分,还将为堆分配TLS的单独空间。

因此,最后,您真正拥有的只是一个通用的内存分配器(即堆),而其他所有东西都是最基础的专用形式。换句话说,如果您愿意放弃“我想要分配(或分配)尽可能少的内容,将其保留我想要的时间,并在需要时随意释放”的某些方面,则可以避免交易可以将通用堆分配器用于另一个模型,该模型可以提供速度,但要付出其他一些限制。

拿栈。与堆相比,它快得令人难以置信,但是两个权衡取舍是:1)释放内存时您无法控制;取而代之的是,一旦函数退出,分配的所有内容都将消失,并且2)由于堆栈的大小通常受到限制,因此您应注意直接在堆栈上分配大量数据。

另一种类型的“内存模型”是几乎每个主要操作系统都通过系统调用提供的虚拟内存管理器(VMM)。从某种意义上说,VMM与堆非常相似,您可以请求任何数量的内存并将其保留任意长的时间。但是,局限性在于您只能以页面大小倍数(例如4KB)分配内存,因此直接使用VMM将在通常一次分配8-24个字节的典型应用程序中造成大量开销。实际上,几乎每个堆实现都是在VMM之上构建的,专门用于允许非常通用的,非专业的小块分配。每当需要更多内存时,Heap就会进入VMM,然后将该内存的许多小块分配给应用程序。

如果您有一个需要分配大块的应用程序,则可以考虑直接进入VMM,尽管某些堆在malloc()内有一个if语句,并且如果块大小大于某个阈值,则只需进入VMM为了你。

池而不是直接使用堆的另一种形式的分配器是池。池是一种专用分配器,其中所有块的大小均相同。池(就像堆栈和TLS一样)建立在堆或VMM之上。池在您分配大量(百万)个相同大小的短期小对象的地方很有用。考虑一个处理传入请求的网络服务。每个客户端请求可能导致分配相同的N字节结构来处理该请求。使用池的权衡在于,每个池只能处理一个块大小(但您可以创建多个池)。池的优点在于,因为所有对象的大小都相同,所以不需要复杂的逻辑。相反,只要您需要一个新块,它就会为您提供最近释放的块。

最后,请记住我提到的硬盘驱动器。您可以拥有一个行为类似于文件系统的内存模型,并复制相同的目录条目和索引节点概念,以允许您按层次分配数据块,其中每个数据块均以路径寻址。这正是tmpfs所做的。

除了我提到的内容之外,我敢肯定还有其他一些更专业的模型,但是最后,由于一切都基于平坦的地址空间(也就是说,直到某些精灵提出了某种怪异的非平坦空间) ),这一切都回到了通用的“内存”分配器,它是VMM还是堆。


1

我能想到的唯一情况是在专用硬件中,所有东西都可能在内存中的固定位置运行。如果要使用完全灵活的程序,则几乎需要当前内存模型中的所有内容。

没有堆栈,您将没有局部变量,调用堆栈等。您为实现而编写的任何其他内容最终都会看起来像堆栈。

静态内存和某些应用程序可能会掉落的堆,但是同样,您将需要将它们以某种形式或其他形式返回,以进行更高级的操作。

因此,如果您发明替代这三者中的任何一者,最终都会看起来很像这三者中的一种……

从另一个角度来看,您可以添加哪些新内容?您可能会争辩说,诸如图形/物理处理器/ cpu缓存/等之类的东西是一个新的内存位置,但实际上它们只是它们的一个单独实例或一种加快对现有模型的访问的方式。

...所以直到有人提出某种巨大的概念上的飞跃,我认为我们很可能不会在很长一段时间内看到该领域的任何重大变化...


4
大多数人倾向于认为当前的方法是最好的/唯一的方法,如果给定空白,只会复制已经存在的方法。在其他人究竟是谁推动技术进步的人。并不是说我个人知道任何严重的竞争模型(除非您算出量子计算机),而是声称一个人可以想出的任何东西看起来都与已经存在的东西本质上是一种循环推理。
亚罗诺(Aaronaught)2013年

@Aaronaught:您的论点的另一面是,其他人会花费大量的时间,金钱和精力在盒子外面思考,而其中每千(可能更多)的人可能最终会推动技术进步,而其他人却无济于事。第一组可能会认为更实用的组将这些现有模型
DXM

@aaronaught我想我用“所以涵盖了这一点,直到有人提出某种巨大的概念性飞跃”;)如果您有更好的替代模型,请随意提出来……否则,抱怨的感觉有点虚伪。当您是其中一员时是“某些人” :)
Tim B

1
@DXM:是吗?我是否说过我们都应该花时间研究新的内存模型?我只是指出一个观点,即一个人只能发明已经发明的东西,这是(重大的)缺陷。
亚伦诺特,2013年

我从未提出过这样的要求
Tim B
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.