一:背景
1. 讲故事
在前一篇大内存排查中,我们看到了Dictionary正在做扩容操作,当时这个字典的count=251w,你把字典玩的66飞起,其实都是底层为你负重前行,比如其中的扩容机制,当你遇到几百万甚至千万的大集合这个扩容机制还真的需要挖一下,免的入戏太深,难以自拔。
二:List扩容机制
1. 如何查看
要想看它的扩容机制,可以用ILSpy去看看List的源码即可,非常简单。
从源码的 int num = (_items.Length == 0) ? 4 : (_items.Length * 2)可以非常清楚的看到,4个空间起步,后面都是*2的扩容,也就说当你有2^(n-1) + 1个元素,实际上你需要占用2^n个空间。
下面我用C#代码演示一下:
static void Main(string[] args)
{
var list1 = Enumerable.Range(0, (int)Math.Pow(2, 22)).ToList();
var list2 = new List(list1);
list2.Add(1);
Console.WriteLine($"list1.Capacity={list1.Capacity}");
Console.WriteLine($"list2.Capacity={list2.Capacity}");
Console.ReadLine();
}
------ output -------
list1.Capacity=4194304
list2.Capacity=8388608
从代码中可以看到,当List中已有 4194304个元素的时候,再往其中塞入一个元素,仅仅是多一个,在底层可是翻倍的空间占用哦,太可气了,要想往深处看可以用windbg看一下各自数组占用大小。
0:000>