[翻译]内存 - 第三部分:管理内存

原文地址:https://techtalk.intersec.com/2013/08/memory-part-3-managing-memory/

# 开发人员的视角

之前的文章中,我们对内存进行了分类并且从外部视角进行了分析。我们看到内存可以用不同的方式进行分配,并具有各种不同的属性。接下来的文章中我们会采用开发人员的视角。

Intersec我们所有的软件都用C来写,这意味着我们经常处理内存管理。我们希望我们的开发人员有关于各种内存池方面的扎实的知识。这篇文章我们会概要的看一下对C程序员来说在Linux上有哪些主要的内存资源。我们也会看到一些内存管理的规则,用于帮助你的程序保持正确和高效。

# 局部性(locality)

我们谈论了很多内核(和硬件)中分配的内存页。CPU使用更小的地址单位:缓存行(cache line)。一个缓存行是64字节大小。这是CPU从主内存取得数据并放到内部各种缓存的大小(注,即一次取64个字节)。

老一点的CPU没有缓存,但是CPU性能的发展比内存总线性能更快(注,原文是that,我认为这里应该是than)。因此,为了避免花费太多的时间从主内存获取数据,CPU在芯片内部直接增加了少量的内存。一开始只是很少的缓存,但是现代CPU可以最多有3级缓存。越接近CPU的缓存就越快。离CPU越远,它的大小就越大。这儿有一张小的表格向我们展示了按照缓存的大小和访问时间排序的各级缓存的一些数据,这些数据来自2010年产的个i5-750CPU:

[翻译]内存 - 第三部分:管理内存_第1张图片

为了避免CPU从内存取数据消耗CPU时间,你必须尝试使用已经在缓存中存在的数据。这就是局部性规则。

这里我们讨论空间局部性和时间局部性:

  • 空间局部性:规划你的程序使一起访问的变量物理上放在一个组里
  • 时间局部性:规划你的代码使得对相同的位置的访问时间上靠的近一些

既然内存是按照缓存行来获取的,一个很好的实例是把经常一起访问的变量按照缓存行分组。一些工具,例如pahole,可以用于检查结构的布局:

struct mem_stack_pool_t {
        const void  *              start;                /*     0     8 */
        size_t                     size;                 /*     8     8 */
        dlist_t                    blk_list;             /*    16    16 */
        mem_stack_frame_t          base;                 /*    32    32 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        mem_stack_frame_t *        stack;                /*    64     8 */
        size_t                     stacksize;            /*    72     8 */
        uint32_t                   minsize;              /*    80     4 */
        uint32_t                   nbpages;              /*    84     4 */
        uint32_t                   nbpops;               /*    88     4 */
        uint32_t                   alloc_nb;             /*    92     4 */
        size_t                     alloc_sz;             /*    96     8 */
        mem_pool_t                 funcs;                /*   104    24 */
        /* --- cacheline 2 boundary (128 bytes) --- */
 
        /* size: 128, cachelines: 2, members: 12 */
};



CPU也有一些简单的访问模式检测。它们被用于内存预取,如果CPU猜到该内存在短时间内很可能会被访问到。当预取做得非常好时,它避免了更多的延迟,因为在CPU实际需要时,内存数据已经被取到。

你可以在这里发现更多的细节[What every programmer should know about memory]。

(未完)

你可能感兴趣的:(linux)