go中Slice扩容机制新更新

前言

对于golang初学者来讲,golang的扩容机制是比较懵逼的,而在go1.18中golang的扩容机制迎来了更新


一、旧版本

go 复制代码
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
	newcap = cap
} else {
	if old.len < 1024 {
		newcap = doublecap
	} else {
		// Check 0 < newcap to detect overflow
		// and prevent an infinite loop.
		for 0 < newcap && newcap < cap {
			newcap += newcap / 4
		}
		// Set newcap to the requested cap when
		// the newcap calculation overflowed.
		if newcap <= 0 {
			newcap = cap
		}
	}
}

这是$GOROOT/src/runtime/slice.go里的源码,说的比较清楚,

首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)。 否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap), 否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap) 如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)。

二、go1.18的更新

这是go1.18中的源码

go 复制代码
newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		const threshold = 256
		if old.cap < threshold {
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			for 0 < newcap && newcap < cap {
				// Transition from growing 2x for small slices
				// to growing 1.25x for large slices. This formula
				// gives a smooth-ish transition between the two.
				newcap += (newcap + 3*threshold) / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
			if newcap <= 0 {
				newcap = cap
			}
		}
	}

对比新版扩容与旧版可以看出差别就是: 旧版是和1024比较, 而新版是和256比较, 并且系数也从1.25变成了 newcap += (newcap + 3*threshold) / 4

总结

在1.18中,优化了切片扩容的策略2,让底层数组大小的增长更加平滑: 通过减小阈值并固定增加一个常数,使得优化后的扩容的系数在阈值前后不再会出现从2到1.25的突变,该commit作者给出了几种原始容量下对应的"扩容系数":

相关推荐
拾贰_C2 小时前
【SpringBoot】MyBatisPlus(MP | 分页查询操作
java·spring boot·后端·spring·maven·apache·intellij-idea
就叫飞六吧7 小时前
Spring Security 集成指南:避免 CORS 跨域问题
java·后端·spring
冼紫菜8 小时前
[特殊字符]CentOS 7.6 安装 JDK 11(适配国内服务器环境)
java·linux·服务器·后端·centos
秋野酱9 小时前
Spring Boot 项目的计算机专业论文参考文献
java·spring boot·后端
香饽饽~、10 小时前
【第二篇】 初步解析Spring Boot
java·spring boot·后端
你是狒狒吗10 小时前
消息队列了解一哈
后端
Chandler2411 小时前
Go语言 GORM框架 使用指南
开发语言·后端·golang·orm
蚂蚁在飞-12 小时前
Golang基础知识—cond
开发语言·后端·golang
程序员爱钓鱼18 小时前
匿名函数与闭包(Anonymous Functions and Closures)-《Go语言实战指南》原创
后端·golang