Golang slice 通过growslice调用nextslicecap计算扩容
先来看一段代码
code: e := []int64{1, 2, 3}fmt.Println("cap of e before:", cap(e))e = append(e, 4, 5, 6, 7)fmt.Println("cap of e after:", cap(e))output:cap of e before: 3
cap of e after: 8
为什么容量是8?
append了的4个元素,如果是原来的2倍也才6个,小于长度7,所以容量赋值长度7
内存分配,为了高效使用需要对齐,找到合适的span对象
capmem = roundupsize(uintptr(newcap) * ptrSize) ptrSize 8字节
capmem = roundupsize(7*8)
capmem = 64
newcap = int(capmem / ptrSize)
newcap = 8
_MaxSmallSize = 32768smallSizeDiv = 8smallSizeMax = 1024largeSizeDiv = 128_NumSizeClasses = 68_PageShift = 13maxObjsPerSpan = 1024
)var class_to_size = [_NumSizeClasses]uint16{0, 8, 16, 24, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384, 416, 448, 480, 512, 576, 640, 704, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2688, 3072, 3200, 3456, 4096, 4864, 5376, 6144, 6528, 6784, 6912, 8192, 9472, 9728, 10240, 10880, 12288, 13568, 14336, 16384, 18432, 19072, 20480, 21760, 24576, 27264, 28672, 32768}
var class_to_allocnpages = [_NumSizeClasses]uint8{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 2, 3, 1, 3, 2, 3, 4, 5, 6, 1, 7, 6, 5, 4, 3, 5, 7, 2, 9, 7, 5, 8, 3, 10, 7, 4}
var class_to_divmagic = [_NumSizeClasses]uint32{0, ^uint32(0)/8 + 1, ^uint32(0)/16 + 1, ^uint32(0)/24 + 1, ^uint32(0)/32 + 1, ^uint32(0)/48 + 1, ^uint32(0)/64 + 1, ^uint32(0)/80 + 1, ^uint32(0)/96 + 1, ^uint32(0)/112 + 1, ^uint32(0)/128 + 1, ^uint32(0)/144 + 1, ^uint32(0)/160 + 1, ^uint32(0)/176 + 1, ^uint32(0)/192 + 1, ^uint32(0)/208 + 1, ^uint32(0)/224 + 1, ^uint32(0)/240 + 1, ^uint32(0)/256 + 1, ^uint32(0)/288 + 1, ^uint32(0)/320 + 1, ^uint32(0)/352 + 1, ^uint32(0)/384 + 1, ^uint32(0)/416 + 1, ^uint32(0)/448 + 1, ^uint32(0)/480 + 1, ^uint32(0)/512 + 1, ^uint32(0)/576 + 1, ^uint32(0)/640 + 1, ^uint32(0)/704 + 1, ^uint32(0)/768 + 1, ^uint32(0)/896 + 1, ^uint32(0)/1024 + 1, ^uint32(0)/1152 + 1, ^uint32(0)/1280 + 1, ^uint32(0)/1408 + 1, ^uint32(0)/1536 + 1, ^uint32(0)/1792 + 1, ^uint32(0)/2048 + 1, ^uint32(0)/2304 + 1, ^uint32(0)/2688 + 1, ^uint32(0)/3072 + 1, ^uint32(0)/3200 + 1, ^uint32(0)/3456 + 1, ^uint32(0)/4096 + 1, ^uint32(0)/4864 + 1, ^uint32(0)/5376 + 1, ^uint32(0)/6144 + 1, ^uint32(0)/6528 + 1, ^uint32(0)/6784 + 1, ^uint32(0)/6912 + 1, ^uint32(0)/8192 + 1, ^uint32(0)/9472 + 1, ^uint32(0)/9728 + 1, ^uint32(0)/10240 + 1, ^uint32(0)/10880 + 1, ^uint32(0)/12288 + 1, ^uint32(0)/13568 + 1, ^uint32(0)/14336 + 1, ^uint32(0)/16384 + 1, ^uint32(0)/18432 + 1, ^uint32(0)/19072 + 1, ^uint32(0)/20480 + 1, ^uint32(0)/21760 + 1, ^uint32(0)/24576 + 1, ^uint32(0)/27264 + 1, ^uint32(0)/28672 + 1, ^uint32(0)/32768 + 1}
var size_to_class8 = [smallSizeMax/smallSizeDiv + 1]uint8{0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
var size_to_class128 = [(_MaxSmallSize-smallSizeMax)/largeSizeDiv + 1]uint8{32, 33, 34, 35, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, 41, 41, 41, 42, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67}func divRoundUp(n, a uintptr) uintptr {// a is generally a power of two. This will get inlined and// the compiler will optimize the division.return (n + a - 1) / a
}func roundupsize(size uintptr) uintptr {if size < _MaxSmallSize {if size <= smallSizeMax-8 {return uintptr(class_to_size[size_to_class8[divRoundUp(size, smallSizeDiv)]])} else {return uintptr(class_to_size[size_to_class128[divRoundUp(size-smallSizeMax, largeSizeDiv)]])}}if size+_PageSize < size {return size}return alignUp(size, _PageSize)
}
计算容量
< 256 容量*2,反之
容量 += 容量+3*256 >> 2 (二进制中右移n位,相当于除以2的n次方_
举例512扩容
512 += (512 + 256 * 3)>>2
cap = 512 + 320 = 832
func nextslicecap(newLen, oldCap int) int {newcap := oldCapdoublecap := newcap + newcapif newLen > doublecap {return newLen}const threshold = 256if oldCap < threshold {return doublecap}for {// 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) >> 2// We need to check `newcap >= newLen` and whether `newcap` overflowed.// newLen is guaranteed to be larger than zero, hence// when newcap overflows then `uint(newcap) > uint(newLen)`.// This allows to check for both with the same comparison.if uint(newcap) >= uint(newLen) {break}}// Set newcap to the requested cap when// the newcap calculation overflowed.if newcap <= 0 {return newLen}return newcap
}func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) slice {...newcap := nextslicecap(newLen, oldCap)var overflow boolvar lenmem, newlenmem, capmem uintptr// Specialize for common values of et.Size.// For 1 we don't need any division/multiplication.// For goarch.PtrSize, compiler will optimize division/multiplication into a shift by a constant.// For powers of 2, use a variable shift.switch {case et.Size_ == 1:lenmem = uintptr(oldLen)newlenmem = uintptr(newLen)capmem = roundupsize(uintptr(newcap))overflow = uintptr(newcap) > maxAllocnewcap = int(capmem)case et.Size_ == goarch.PtrSize:lenmem = uintptr(oldLen) * goarch.PtrSizenewlenmem = uintptr(newLen) * goarch.PtrSizecapmem = roundupsize(uintptr(newcap) * goarch.PtrSize)overflow = uintptr(newcap) > maxAlloc/goarch.PtrSizenewcap = int(capmem / goarch.PtrSize)case isPowerOfTwo(et.Size_):var shift uintptrif goarch.PtrSize == 8 {// Mask shift for better code generation.shift = uintptr(sys.TrailingZeros64(uint64(et.Size_))) & 63} else {shift = uintptr(sys.TrailingZeros32(uint32(et.Size_))) & 31}lenmem = uintptr(oldLen) << shiftnewlenmem = uintptr(newLen) << shiftcapmem = roundupsize(uintptr(newcap) << shift)overflow = uintptr(newcap) > (maxAlloc >> shift)newcap = int(capmem >> shift)capmem = uintptr(newcap) << shiftdefault:lenmem = uintptr(oldLen) * et.Size_newlenmem = uintptr(newLen) * et.Size_capmem, overflow = math.MulUintptr(et.Size_, uintptr(newcap))capmem = roundupsize(capmem)newcap = int(capmem / et.Size_)capmem = uintptr(newcap) * et.Size_}...memmove(p, oldPtr, lenmem)return slice{p, newLen, newcap}
}
相关文章:
Golang slice 通过growslice调用nextslicecap计算扩容
先来看一段代码 code: e : []int64{1, 2, 3}fmt.Println("cap of e before:", cap(e))e append(e, 4, 5, 6, 7)fmt.Println("cap of e after:", cap(e))output:cap of e before: 3 cap of e after: 8 为什么容量是8? append了的4个元素&…...

HTTP 协商缓存 Last-Modified,If-Modified-Since
浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone header加上Last-Modified属性(表示这个资源在服务器上的最后修改时间): ----------------------------------------------------------------…...

零基础教程:Yolov5模型改进-添加13种注意力机制
1.准备工作 先给出13种注意力机制的下载地址: https://github.com/z1069614715/objectdetection_script 2.加入注意力机制 1.以添加SimAM注意力机制为例(不需要接收通道数的注意力机制) 1.在models文件下新建py文件,取名叫Sim…...
vue截取地址参数
const getQueryValueFn () >{// 获取当前页面的URLconst currentURL window.location.href;//创建一个URL对象来解析当前URL。URL对象提供了方便的属性和方法来处理URL的各个部分const url new URL(currentURL);// 使用URLSearchParams获取查询参数const queryParams ne…...

ubuntu 14.04更新GCC版本
按最基本的apt-get install gcc-8,不成功,提示如下。 按网上说的:apt-get update ,apt-get upgrade 后都无效果。 apt-cache search get 搜索后,发现资源链接里最新的也只有4.8.4所以不行。 需要更新资源链接,镜像地…...
AndroidUtil - 强大易用的安卓工具类库
官网 https://github.com/Blankj/AndroidUtilCode/blob/master/README-CN.md 项目介绍 AndroidUtilCode 🔥 是一个强大易用的安卓工具类库,它合理地封装了安卓开发中常用的函数,具有完善的 Demo 和单元测试,利用其封装好的 API…...
[多态设计模式]枚举
背景: 游戏服务器中,多态可以说体现的淋漓尽致。 如: 1.开启条件。有的系统是根据玩家等级,有的是根据通关第几关。 2.商店可能有不同类型的商店。 3.任务系统中,不同的计数类型,不同的任务目标类型。…...

【QT】QRadioButton的使用(17)
QRadioButton这个控件在实际项目中多用于多个QRadioButton控件选择其中一个这样的方式去执行,那么,今天这节就通过几个简单的例子来好好了解下QRadioButton的一个使用。 一.环境配置 1.python 3.7.8 可直接进入官网下载安装:Download Pyt…...

力扣:105. 从前序与中序遍历序列构造二叉树(Python3)
题目: 给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 来源:力扣(LeetCode) 链接:力扣&am…...
【含java2023面试题】HashMap、HashTable、ConcurrentHashMap
作为Java中最常用的Map集合,HashMap、HashTable和ConcurrentHashMap都是线程安全的,但它们之间有什么区别呢?在本文中,我们将深入探讨这三种Map集合的区别,并通过Java代码示例来演示它们之间的差异。 AI绘画关于SD,MJ…...

AT24C02芯片
AT24C02简介: AT24C01/02/04/08/16...是一个 1K/2K/4K/8K/16K 位串行 CMOS内部有9个字节; 该器件通过 I2C 总线接口进行 操作,它有一个专门的写保护功能; 基于51 他有这个芯片操作 时序: AT24C02软件编程: …...

Python+Django前后端分离
程序示例精选 PythonDjango前后端分离 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对《PythonDjango前后端分离》编写代码,代码整洁,规则,易读。 学习与应…...

win11系统固定到快速访问的文件夹无法调整顺序的问题
最近在使用win11系统时,固定到快速访问的文件夹无法调整顺序。网上搜了一大圈没有对应的解决方法,柳暗花明,在博主yin0hao的一篇文章中找到了类似的,跟着做了一下,结果问题也解决了。在此记录。 在文件资源管理器地址…...

短视频矩阵系统,短视频矩阵源码技术开发
开发短视频矩阵系统的源码需要以下步骤: 确定系统需求:根据客户的需求,确定系统的功能和特点,例如用户注册登录、视频上传、视频浏览、评论点赞等。 设计系统架构:根据系统需求,设计系统的整体架构&#x…...

Flask 数据库 连接池、DBUtils、http 连接池
1、DBUtils 简介、使用 DBUtils 简介 DBUtils 是一套用于管理 数据库 "连接池" 的Python包,为 "高频度、高并发" 的数据库访问提供更好的性能,可以自动管理连接对象的创建和释放。并允许对非线程安全的数据库接口进行线程安全包装…...

Day 01 python学习笔记
1、引入 让我们先写第一个python程序(如果是纯小白的话) 因为我们之前安装了python解释器 所以我们直接win r ---->输入cmd(打开运行终端) >python #(在终端中打开python解释器)>>>pri…...
CSharp Library develop histroy
1. .NET FRAMEWORK 发展版本 版本 完整版本号 发行日期 Visual Studio Windows 默认安装 1.0 1.0.3705.0 2002-02-13 Visual Studio .NET 2002 Windows XP Media Center Edition Windows XP Tablet PC Edition 1.1 1.1.4322.573 2003-04-24 Visual Studio .NET 2…...

林木种苗生产vr虚拟实训教学降低培训等待周期
林业种植管理在保护水土流失、气候变化及经济社会发展中发挥重要的作用,林业教学往往需要进入林区进行实操察验,在安全性、时间及效率上难以把控,因此有更多林业畜牧院校创新性地引进VR虚拟现实技术。 在林业领域,实地调查是获取准…...

LabVIEW在运行时调整表控件列宽
LabVIEW在运行时调整表控件列宽 如何在LabIEW中运行时调整表控件的列宽大小? 在VI运行时,有两种不同的方法可以更改表中列的宽度。首先,可以使用鼠标手动更改它们;其次,可以从框图中以编程方式更改它们。 手动更改列宽 只有在…...
【6 ElementUI Tabs控件第二个tab页签Div宽度缩小的问题】
背景 在使用ElementUI的Tabs 控件时,发现第二个tabs 内容的Div宽度用的百分比,然后就会缩小,导致内容变形,这边的处理方法就是拿到一个tabs 内容的div的offsetWidth,然后将这个width赋值给第二个Div的width即可。 代…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...