术语竞技场与记忆有什么关系?

Noc*_*rno 92 c c++ memory-management

我正在读一本关于记忆的书作为编程概念.在后面的一章中,作者大量使用了竞技场这个词,但从未定义它.我已经搜索了这个词的含义以及它与记忆的关系,并没有发现任何东西.以下是作者使用该术语的一些背景:

"序列化的下一个例子包含一个称为特定领域内存分配的策略."

"......在处理内存泄漏或从特定领域分配时,这很有用."

"......如果我们想要释放内存,那么我们将解除整个竞技场."

作者在一章中使用了100多次这个词.词汇表中唯一的定义是:

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

在给出这些背景的情况下,任何人都能为我定义竞技场吗?

Ker*_* SB 98

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

char * arena = malloc(HUGE_NUMBER);

unsigned int current = 0;

void * my_malloc(size_t n) { current += n; return arena + current - n; }
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 这是一个很好的答案,但请考虑删除或修改最后一段.你真的根本不需要任何证据.任何时候你知道*你将如何使用内存,你不仅仅知道一个"好"的通用分配器,如果你使用这些知识,你的自定义分配器将永远胜利.分配器不是魔术.如果你有很多项目都在相同的,定义明确的时间点死亡,那么竞技场很有用.这几乎是你需要知道的全部内容.这不是火箭科学. (21认同)
  • @ruakh我只是不喜欢这种货物崇拜的心态,在世界各地重复百万次作为"智慧"."C++之神将它交给了我们,所以我们必须使用它." 而我最喜欢的是:"这很神奇." 不,这不是魔术.它只是一个非常简单的算法,即使是计算机也可以运行它.在我的书中,这与魔术相差甚远.我的猜测:你低估了内存分配对性能有多大的影响,并高估了复杂的竞技场.性能是否比开发人员时间更重要是一个商业决策,在SO上讨论是没有意义的. (14认同)
  • @AndreasHaferburg:我最后的建议并不是说原则上很难"比默认更好",而是维护自定义解决方案的成本很高(有人必须写它,记录它,得到它是的,其他人必须修复错误,每个人都必须审查并重新验证原始假设作为使用价差,并且您需要证据证明该费用是合理的. (10认同)
  • @AndreasHaferburg:来自标准库的内存分配器自动比自定义编写自己有一个巨大的优势,即你不必编写/测试/调试/维护等等.即使你确定没有证据表明你通过管理自己的分配可以提高性能,在决定这种改进值得权衡之前,您仍需要良好的证据. (9认同)
  • @AndreasHaferburg:当然,tcmalloc使用了一些特定的算法,其背后的想法很容易解释,但实现仍然很复杂而且非常重要.最重要的是,它需要特定于平台的知识才能使内存排序正确.我使用"魔法"来处理用户根本无法写入的内容(如高效的互斥锁或tcmalloc,或lambda的类型名称),或仅限于极端英雄(如std :: function); 我不是说它"不可理解". (7认同)
  • 我仍然会说,收集需要实施的证据非常重要.只需要找到默认的实现来处理你想要的特殊情况以及最有效的专业化,就可以轻松地进行大规模的游览. (5认同)

Mik*_*ike 9

我会把这个作为一个可能的答案.

•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.

我将添加Wikipedia的同义词:region,zone,arena,area或memory context.

基本上它是你从操作系统获得的内存,然后分出来,然后可以立即释放.这样做的好处是重复的小调用malloc()可能成本很高(每个内存分配都有性能成本:在程序的逻辑地址空间中分配内存所花费的时间以及将该地址空间分配给物理内存所需的时间)在那里,如果你知道一个球场,你可以给自己一大块记忆,然后把它交给你的变量/你需要它.


Ada*_*eld 5

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

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

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


Rah*_*thi 5

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

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

您也可以参考以下链接:

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

  • 这似乎是从http://www.bozemanpass.com/info/linux/malloc/Linux_Heap_Contention.html复制粘贴而来的。 (5认同)
  • 仅供参考,发布链接时,您应该发布摘要,以便链接的文章消失时,您的帖子仍然有用。 (3认同)