美文网首页
浅谈容器扩容参数

浅谈容器扩容参数

作者: 太刀 | 来源:发表于2021-10-02 23:53 被阅读0次
美女

在编码时我们经常使用各种容器来做基本的数据结构,比如 C++ STL 中的 vector, C# 的 List 和 Dictionary 等,这篇文章我们简单聊一下这些容器在发生扩容时的扩容系数选择的话题

1. 什么是容器的扩容

虽然容器的使用方法和特点各异,但整体来说底层的存储结构基本上都是基于数组,例如 C++ 中的 vector、C# 中的 List 底层都是使用数组来存放数据,那么容器中的数组长度如何确定呢?

  • 容器会进行预分配空间(capacity)
  • 通常容器会提供接口,让我们在初始化时指定容器中元素的个数(size 或 length),容器底层会根据元素个数分配对应的数组长度
  • 如果初始化时没有提供元素个数,则会初始化一个默认长度(vector 和 List 默认都是4)
  • 那么当容器元素超过预分配空间时,会重新分配更多的空间,以存放更多的元素,这个过程就是扩容
    容器扩容的操作:
  • 分配新的内存空间
  • 搬移元素,将元素全部复制到新分配的内存空间
  • 释放旧空间

2. 容器扩容的时机

那么容器的扩容发生在什么时候呢?

  • 第一种情况:当容器调用添加元素(push_back, Add等)的方法时,如果当前 capacity 无法容纳新元素,会触发扩容机制
  • 第二种情况:基于哈希表的容器(如Dictionary)当哈希冲突超过某个阈值时,触发扩容机制

3. 容器扩容的系数选择逻辑

扩容时分配多大的新空间比较合适呢?(此处综合考虑到普遍情况下的内存分配、元素复制消耗、扩容次数等),假设当前容量是x,那么新分配的容量为 n*x,对于不同容器,不同的版本实现,此处的 n 不尽相同

3.1 C++ STL vector 的扩容系数

  • VC 版本的 vector 扩容系数为 1.5,每次扩容时分配 1.5 倍的新空间
  • gcc 版本的 vector 扩容系数为 2,每次扩容时分配 2 倍的新空间

3.2 C# List 的扩容系数

查看 List源码可知,C# List 的扩容系数是 2,扩容是分配 2 倍新空间

对于 vector 和 List 来说,1.5 的扩容系数是比 2 更好的选择。使用扩容系数 2 时产生的问题在于,每次新分配的空间必然刚好大于之前分配的空间之和,之前分配的空间无法复用,使用1.5 是一个更好的选择,便于复用之前分配过的空间,详情可以参考 MiloYip的回答

3.3 C# Dictionary 的扩容系数

和列表不同,Dictionary 由于底层哈希桶数组的存在,添加元素时需要考虑元素哈希值冲突,扩容应该能够尽量避免哈希冲突的产生,所以 Dictionary 的扩容方法是,取小于 2*x的最小质数,为什么要取质数呢?这是因为哈希桶的长度为质数时,能够使得哈希值分配更均匀,最大程度的减少哈希冲突的发生,理论依据简单概括:

  • 偶数除以偶数,得到的余数一定是个偶数。
  • 偶数除以质数,小于质数得到的余数是偶数,大于质数得到的是奇数。
  • 奇数除以偶数,得到的余数一定是个奇数。
  • 奇数除以质数,小于质数得到的余数是奇数,大于质数得到的是偶数。

陷入以质数做除数,得到的结果的可能性更多,也就说明了质数能够使数据分配的更均匀,达到了减少哈希冲突的目的。

相关文章

  • JDK1.7 版本中 HashMap 扩容

    扩容扩容是指当容器中元素的数量达到某个阈值时,容器自己进行的容量翻倍的操作。 JDK1.7 HashMap 扩容方...

  • Docker cgroup详解

    最近在测试容器垂直扩容功能,通过探测容器的CPU使用率来判断该容器是否超过预设阈值而需要扩容来增加CPU limi...

  • C++ 数据结构与算法

    C++ 容器与算法 vector 容器: 动态数组,可动态扩容,扩容时重新开辟原有长度2倍的长度,然后将原有的数据...

  • 【区块链】区块链扩容是什么?

    一、为何要扩容? 一般我们所理解扩容是什么呢?即当某个容器或承载物不足以支撑或承载现有事物需求时,我们通过扩大容器...

  • [容器化技术之九] 容器监控

    一、容器监控概要   使用docker compose组合应用并利用scale可以实现快速对容器扩容。由于dock...

  • docker容器磁盘扩容

    一、配置文件里更改容器创建时的默认磁盘大小 ubutntu [root@ip-10-10-125-7~]#cat/...

  • 容器内核参数

    容器安全-内核参数?容器与宿主机共用内核,修改内核参数可能会影响到宿主机和其他容器。非特权容器大部分内核参数无法修...

  • docker 使用细节

    容器添加启动参数 通过 docker 命令直接运行容器,可以在容器后面添加参数,例如, 使用 docker-com...

  • docker容器overlay存放目录磁盘空间已满(解决)

    问题 云服务器系统空间太小,导致docker 容器中日记文件存储占用较多,需要挂载数据盘进行扩容 思路: 1.扩容...

  • 一图看懂 spring bean 的生命周期

    注:容器关闭:容器指的是 ApplicationContext 容器。aware容器参数:aware 了解、明白之...

网友评论

      本文标题:浅谈容器扩容参数

      本文链接:https://www.haomeiwen.com/subject/hhxinltx.html