站长网 语言 Slice 扩容后容量及内存怎样计算?

Slice 扩容后容量及内存怎样计算?

1. 扩容后预估容量假设现在有一个长度为 2 的切片,对其进行扩容,增加三个元素sli := []int{1,2}sli = append(sli, 3, 4, 5)对于扩容后的切片,长度为 5,这一点没有任何争议。但容量呢?难道也是 5?经过运行验证,实际的容量为 6 。什么情况?这 6 是如何

1. 扩容后预估容量

假设现在有一个长度为 2 的切片,对其进行扩容,增加三个元素

 

sli := []int{1,2} 

sli = append(sli, 3, 4, 5) 

对于扩容后的切片,长度为 5,这一点没有任何争议。

 

但容量呢?难道也是 5?

 

经过运行验证,实际的容量为 6 。

 

什么情况?这 6 是如何计算出来的呢?

 

这就不得不去 Go 源代码中一探究竟,在 runtime/slice.go 关于 slice 扩容增长的代码如下:

 

newcap := old.cap 

if newcap+newcap < cap { 

    newcap = cap 

} else { 

    for { 

        if old.len < 1024 { 

            newcap += newcap 

        } else { 

            newcap += newcap / 4 

        } 

        if newcap >= cap { 

            break 

        } 

    } 

对于这段代码,只要理解前两行,其他的就不攻自破了

 

第一行的 old.cap:扩容前的容量,对于此例,就是 2

第二行的 cap:扩容前容量加上扩容的元素数量,对于此例,就是 2+3

整段代码的核心就是要计算出扩容后的预估容量,也就是 newcap,计算的具体逻辑是:

 

若 old.cap * 2 小于 cap,那 newcap 就取大的 cap

若 old.cap * 2 大于 cap,并且old.cap 小于 1024,那 newcap 还是取大,也即 newcap = old.cap * 2

若 old.cap * 2 大于 cap,但是old.cap 大于 1024,那两倍冗余可能就有点大了,系数换成 1.25,也即 newcap = old.cap * 2

但 newcap 只是预估容量,并不是最终的容量,要计算最终的容量,还需要参考另一个维度,也就是内存分配。

 

 2. 内存的分配规律

举个现实中的例子来说

 

你家里有五个人,每个人都想吃绿豆糕,因此你的需求就是 5,对应上例中的 cap ,于是你就到超市里去买。

 

但超市并不是你家开的,绿豆糕都是整盒整盒的卖,没有卖散的,每盒的数量是 6 个,因此你最少买 6 个。

 

每次购买的最少数量,就可以类比做 Go 的内存分配规律。

 

只有了解了 Go 的内存分配规律,我们才能准确的计算出我们最少得买多少的绿豆糕(得申请多少的内存,分配多少的容量)。

本文来自网络,不代表站长网立场,转载请注明出处:https://www.tzzz.com.cn/html/biancheng/yuyan/2021/1104/19756.html

作者: dawei

【声明】:站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。
联系我们

联系我们

0577-28828765

在线咨询: QQ交谈

邮箱: xwei067@foxmail.com

工作时间:周一至周五,9:00-17:30,节假日休息

返回顶部