竞技场一词与记忆有关的含义是什么?


100

我正在读一本关于内存的编程概念书。在后面的章节中,作者大量使用了arena一词,但从未定义。我搜索了单词的含义以及它与记忆的关系,但没有发现任何问题。以下是作者使用该术语的几种情况:

“序列化的下一个示例包含了一种从特定场所进行的称为内存分配的策略。”

“ ...在处理内存泄漏或从特定场所进行分配时,这很有用。”

“ ...如果我们想重新分配内存,那么我们将重新分配整个竞技场。”

作者在一章中使用了100次以上的术语。词汇表中的唯一定义是:

从竞技场分配 -先分配竞技场,然后由程序本身(而不是由进程内存管理器)管理竞技场内的分配/取消分配的技术;用于复杂数据结构和对象的压缩和序列化,或用于安全关键和/或容错系统中的内存管理。

在这些情况下,谁能为我定义竞技场


这本书叫什么名字?
yaobin

1
Frantisek Franek将@yaobin内存作为C和C ++中的编程概念。
Nocturno

Answers:


111

竞技场只是一个巨大的连续内存,您可以分配一次,然后通过分发一部分内存来手动管理内存。例如:

char * arena = malloc(HUGE_NUMBER);

unsigned int current = 0;

void * my_malloc(size_t n) { current += n; return arena + current - n; }

关键是您可以完全控制内存分配的工作方式。您唯一无法控制的是对初始分配的单个库调用。

一种流行的用例是,每个区域仅用于分配一个固定大小的内存块。在这种情况下,您可以编写非常有效的回收算法。另一个用例是每个“任务”都有一个竞技场,当您完成任务后,您可以一次性释放整个竞技场,而不必担心跟踪单个的解除分配。

这些技术中的每一种都是非常专业的,并且通常仅在您确切知道您在做什么以及为什么正常的库分配不够好时才派上用场。请注意,一个好的内存分配器本身已经可以做很多事情了,在开始自己处理内存之前,您需要大量的证据来证明这还不够好。


25
这是一个很好的答案,但是请考虑删除或修改最后一段。您真的根本不需要任何证据。每当您知道如何使用内存时,您将不仅仅知道一个“好的”通用分配器,而且如果您使用此知识,则自定义分配器将永远赢。分配者不是魔术。如果您有很多物品都在相同的明确定义的时间点死亡,那么竞技场会很有用。这就是您几乎需要知道的所有内容。这不是火箭科学。
Andreas Haferburg '16

11
@AndreasHaferburg:与自定义编写自己的内存相比,标准库中的内存分配器自动具有巨大的优势,即您不必编写/测试/调试/维护等。即使您确定没有证据表明自己可以通过管理自己的分配来提高性能,因此在确定这种改进值得权衡之前,您仍然需要充分的证据。
ruakh

17
@ruakh我只是不喜欢这种愚蠢的思想,在世界各地以“智慧”重复一百万次。“ C ++的众神把它交给了我们,所以我们必须使用它。” 我最喜欢的是:“这很神奇。” 不,这不是魔术。这只是一个非常简单的算法,即使是计算机也可以运行它。在我的书中,这离魔术还很远。我的猜测:您低估了内存分配对性能的影响,并高估了舞台的复杂性。性能是否比开发人员的时间更重要是一个业务决策,因此在SO上进行讨论是毫无意义的。
安德烈亚斯·哈弗堡

8
@AndreasHaferburg:当然,tcmalloc使用了一些特定的算法,其背后的思想很容易解释,但是实现仍然很复杂且不简单。最重要的是,它需要特定于平台的知识才能正确地进行内存排序。我将“魔术”用于用户根本无法移植的东西(例如有效的互斥锁或tcmalloc或lambda的类型名称),或仅具有极高的英雄性(例如std :: function);我并不是说它“无法理解”。
Kerrek SB

12
@AndreasHaferburg:我最后的建议不是说原则上很难“比默认更好”,而是维护定制解决方案的成本很高(有人必须编写,记录,获取它)。是的,其他人必须修复错误,并且每个人都必须检查并重新验证原始假设(随着使用范围的扩大),并且您需要证据来证明这笔费用是合理的。
卡雷克SB

10

我将用这个作为可能的答案。

•Memory Arena (also known as break space)--the area where dynamic runtime memory is stored. The memory arena consists of the heap and unused memory. The heap is where all user-allocated memory is located. The heap grows up from a lower memory address to a higher memory address.

我将添加维基百科的同义词:区域,区域,竞技场,区域或内存上下文。

基本上,它是您从操作系统获得的内存,然后分配出去,然后可以一次释放所有内存。这样做的好处是,重复进行小的调用malloc()可能会很昂贵(每个内存分配都有性能成本:在程序的逻辑地址空间中分配内存所花费的时间以及将该地址空间分配给物理内存所花费的时间)好像您知道一个棒球场一样,您可以给自己分配很大的内存,然后根据需要将其分配给变量。


5

可以将其视为“堆”的同义词。通常,您的进程只有一个堆/区域,所有内存分配都从那里进行。

但是,有时您会遇到将一系列分配组合在一起的情况(例如,为了提高性能,避免出现碎片等)。在这种情况下,最好分配一个新的堆/区域,然后对于任何分配,您都可以决定从哪个堆进行分配。

例如,您可能有一个粒子系统,其中频繁分配和释放许多相同大小的对象。为了避免碎片化内存,您可以从堆中分配仅用于这些粒子的每个粒子,而所有其他分配都将来自默认堆。


5

http://www.bozemanpass.com/info/linux/malloc/Linux_Heap_Contention.html

libc.so.x共享库包含glibc组件,并且堆代码位于其中。堆的当前实现使用多个称为arenas的独立子堆。每个竞技场都有自己的互斥量,以进行并发保护。因此,如果进程的堆中有足够的竞技场,并且有一种在线程之间平均分配线程的堆访问的机制,则互斥体争用的可能性应该很小。事实证明,这对分配很有效。在malloc()中,进行测试以查看当前线程的当前目标竞技场的互斥锁是否空闲(trylock)。如果是这样,那么竞技场现在将被锁定,分配将继续进行。如果互斥锁很忙,则依次尝试每个剩余的竞技场,如果互斥锁不忙,则使用它们。如果没有锁定就不能锁定任何竞技场,则会创建一个新的新竞技场。根据定义,此竞技场尚未锁定,因此分配可以立即进行而不会阻塞。最后,线程最后使用的竞技场ID保留在线程本地存储中,并随后用作该线程下一次调用malloc()时尝试的第一个竞技场。因此,对malloc()的所有调用将继续进行而不会阻塞。

您也可以参考以下链接:

http://www.codeproject.com/Articles/44850/Arena-Allocator-DTOR-and-Embedded-Preallocated-Buf


3
仅供参考,发布链接时,您应该发布摘要,以便链接的文章消失时,您的帖子仍然有用。
stonemetal 2012年

5
这似乎是来自bozemanpass.com/info/linux/malloc/Linux_Heap_Contention.html的复制粘贴。请逐字记下您的来源。
jscs 2012年
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.