Blink内存分配器PartitionAlloc

来源:互联网 发布:全宋词软件下载 编辑:程序博客网 时间:2024/06/15 01:01

    PartitionAlloc是Blink模块的内存分配器,并为此在性能和安全性方面做了专门的优化,其目的就是为Blink中的所有对象分配内存空间(另外一个更利于与垃圾回收机制结合的OilPan方案也正在实施中)。


   PartitionAlloc主要包含四个分区,每个分区都是一个包含特定类型对象的堆空间;因此PartitionAlloc将按照所分配对象的类型在以下四个分区中分配空间:

  • Buffer分区:主要分配变长对象或者是内容可能会被用户脚本篡改的对象,如Vector、HashTable、ArrayBufferContent、String等容器类对象;
  • FastMalloc分区:主要分配除其他三种类型之外的比如被标记为USING_FAST_MALLOC的类对象,Blink中大量功能逻辑的内部对象都归于此分区;
  • Node分区(之前版本叫modelobject分区):主要分配dom节点对象,通过重写Node.new/delete运算符实现
  • LayoutObject分区:主要分配layou相关对象,如LayoutObject、PaintLayer、双向字体BidiCharacterRun等对象

        以上每个分区都持有多种/个桶(bucket),每个桶又是一块包含同等大小对象的区域,因此每个对象分配的空间大小都被向上对其到最小桶大小;例如需要为一个128字节的对象分配内存空间,而这个分区只有三种大小 的桶:64B、256B、1024B,那么这个对象就需要被填充至256字节分配于第二个桶内。   实际上,对于以上四种分区:Node分区和LayoutObject分区均有能囊括一定范围大小的对象N*sizeof(void *),其中(N=1,2,...,N_max),不同大小的对象均能分配到对应的桶内(不需要额外填充对其);而Buffer分区和FastMalloc分区则不同,它们都需要支持任意字节大小的对象,出于性能方面的考虑,当然不能为任意大小的对象都创建相应的桶,这就需要选择合适的桶并将对象额外填充部分字节将其填充分配到合适的桶内(这里桶大小以最坏情况下允许10%空间浪费进行选择);此外对于大小超过1MB的大对象则直接以内存映射的方式进行分配。

       从内部实现上四种分区分配器对象定义如下:


实际使用时则都需要指明分配器对象进行分配和回收(如下是Buffer和Node分区的申请和释放用法举例):




性能方面优化措施:

针对每种分配器的用途采取不同的优化方案,由于Node分区和LayoutObject分区对象都只能在renderer主线程进行分配,因此这两种分配器对象的分配就不需要加锁操作;而Buffer分区和FastMalloc分区对象虽然涉及多线程分配(如Renderer主线程、Compositor线程、HTMLParser线程等),但由于Blink中这几种线程争用问题则非常少,因此采用了spinlock加锁操作;另外,之所以要分成这四个分区,性能方面的考虑也是主要因素,这样更利于分支预测、路径最小化、高效内联等措施以提升性能。


安全因素的考虑也是PartitionAlloc最重要的目标之一,这里利用虚拟地址空间来达到安全加固的目的:

不同的分区存在于隔离的地址空间;当某个分区内存页上所有对象都被释放掉之后,其物理内存归还于系统后,但其地址空间仍被此分区保留,这样就保证了此地址空间只能被此分区重用,从而避免了信息泄露;此外,之所以将String、Vector等对象置于Buffer分区,是因为这些对象的长度或内容更易于被用户脚本篡改。



0 0
原创粉丝点击