内存分配(Memory Allocator) 申请和释放内存是应用程序中最常见的操作, 因此发明了许多聪明的技巧使得内存的申请效率更高。然而再聪明的方法也不能弥补这种事实:在很多场合中,一般的内存分配方法非常没有效率。所以为了减少向系统申请内存,我有三个建议。 建议一是使用预分配。我们都知道由于使用静态分配而导致对程序的功能加上人为限制是一种糟糕的设计。但是还是有许多其它很不错的预分配方案。通常认为,通过系统一次性分配内存要比分开几次分配要好,即使这样做在程序中浪费了某些内存。如果能够确定在程序中会有几项内存使用,在程序启动时预分配就是一个合理的选择。即使不能确定,在开始时为请求句柄预分配可能需要的所有内存也比在每次需要一点的时候才分配要好。通过系统一次性连续分配多项内存还能极大减少错误处理代码。在内存比较紧张时,预分配可能不是一个好的选择,但是除非面对最极端的系统环境,否则预分配都是一个稳赚不赔的选择。 建议二是使用一个内存释放分配的lookaside list(监视列表或者后备列表)。基本的概念是把最近释放的对象放到链表里而不是真的释放它,当不久再次需要该对象时,直接从链表上取下来用,不用通过系统来分配。使用lookaside list的一个额外好处是可以避免复杂对象的初始化和清理. 通常,让lookaside list不受限制的增长,即使在程序空闲时也不释放占用的对象是个糟糕的想法。在避免引入复杂的锁或竞争情况下,不定期的“清扫"非活跃对象是很有必要的。一个比较妥当的办法是,让lookaside list由两个可以独立锁定的链表组成:一个"新链"和一个"旧链".使用时优先从"新"链分配,然后最后才依靠"旧"链。对象总是在"新"链上被释放。清除线程则按如下规则运行: 1. 锁住两个链 2. 保存旧链的头结点 3. 把前一个新链挂到旧链的前头 4. 解锁 5. 在空闲时通过第二步保存的头结点开始释放旧链的所有对象。 使用了这种方式的系统中,对象只有在真的没用时才会释放,释放至少延时一个清除间隔期(指清除线程的运行间隔),但同常不会超过两个间隔期。清除线程不会和普通线程发生锁竞争。理论上来说,同样的方法也可以应用到请求的多个阶段,但目前我还没有发现有这么用的。 使用lookaside lists有一个问题是,保持分配对象需要一个链表指针(链表结点),这可能会增加内存的使用。但是即使有这种情况,使用它带来的好处也能够远远弥补这些额外内存的花销。 需要跟我私聊加一下联系方式。。。。。 联系方式:TG;@sunlancdn,QQ;2565734151 ,微信;sunlancdn |