
Go语言
文章平均质量分 52
量子学习法
这个作者很懒,什么都没留下…
展开
-
GO语言栈内存空间管理
栈分配: 编译器+runtime结合实现。编译器会在函数头部安插检查栈大小是否够用代码,不够则调用runtime栈增长的函数。开辟个更大的--拷贝数据--释放原来的 唯一会收缩的地方就是GC。收缩完后再让出CPU。 协成运行结束时, 栈释放到哪里了呢?原创 2023-07-20 15:20:54 · 127 阅读 · 0 评论 -
Go语言mallocgc
runtime中new和make都依赖mallocgc。mallocgc分为4个阶段:辅助GC,空间分配,位图标记,收尾工作。原创 2023-07-20 15:01:18 · 160 阅读 · 0 评论 -
GO语言泛型
也就是泛型会为每个数据类型都生产一套代码,导致可执行文件大小增加,并且使用泛型。但是使用GET 需要使用类型断言,将取出来的数据转为预期数据,空接口本身是一个装箱,会产生内存逃逸和多一部分空间.缓存对象存储多个不同类型的值依然要用空接口,否则。于是1.17GO使用泛型.缓存对象只能存一种类型的值。set一般没什么不方便的。分析可执行文件后:发现。原创 2023-07-19 17:11:35 · 968 阅读 · 0 评论 -
GO语言方法集
因为我们A(a)接受者是第一个参数,而这个参数是动态派发的,参数放在栈的局部变量,编译器在编译阶段不能确定这个量的大小.而指针平台确定了大小也就确定了.面对这个问题,编译器选择为值接受方法生成指针同名方法。那为什么还要生产包装方法呢?主要是为了支持接口.原创 2023-07-19 15:56:54 · 309 阅读 · 0 评论 -
GO语言semaphore信号量
本质上.是结合自旋锁和调度器调度后的锁.不过这种机制适合线程不适合协程.因为调度器调度需要切换线程,而协成切换不能切换线程.一般地,我们唤醒在等待队列中的线程会使用系统调用和切换线程这样的开销比较大.在GO语言中,我们使用semaphore协程信号量来排队。协程等待一个锁如何等待和唤醒呢?原创 2023-07-19 15:40:06 · 522 阅读 · 0 评论 -
GO语言Metex
尝试加锁的G会先自旋几次,若获不到锁,则加入等待队列. 正常模式下,自选和等待队列的一起竞争。在多核下,,且至少有一个其他的P在running,且当前P的本地队列为空才可以自旋转.自旋的条件,当单核下自旋没意义,或者只有一个P时自旋也没意义.因为G频繁的挂起和唤醒会导致开销,为了高吞吐。前面其他位表示多少个等待者。直接加入等待队列FIFO。原创 2023-07-19 15:22:45 · 442 阅读 · 0 评论 -
GO 语言GC
2.每次内存分配都会检查是否需要辅助标记.到GC清扫阶段,内存分配就会促发辅助清扫.例如,分配一个span,若这个span尚未清扫,则需要清扫完再使用.辅助标记和辅助清扫可以避免并发垃圾回收中内存过大的分配压力导致来不及清扫。确定是存活指针还要确定是否指向堆内存:,如果指向堆内存,则把他们加入到GC中进一步扫描.1.若协程需要申请内存,而GC尚未完成,则协程需要当任部分GC工作,借贷尝还机制.写屏障是在写操作中插入指令,目的是把数据对象的修改通知到GC。实现强弱三色不式,为了避免误删,则实现写屏障.原创 2023-07-18 23:35:39 · 986 阅读 · 0 评论 -
GO语言GMP模型
3,信号量,.当检测到信号后,注入一个异步抢占函数调用,处理完信号后返回立刻执行被注入的异步抢占函数,而这个函数就有schedul逻辑 1.14。5,最后再次 本地G, 全局G,netpoll,steal from other p ..若是别人的G则要看看这个G是否有绑定的M.创建一个协程主要是调用newproc函数,而newproc函数是在G0创建的,为什么是G0?创建完新G(协程栈)后,会赋状态Grunnable,.表示可以运行的G..于是看情况调度到别的P。4,全局G调度部分到本地G。原创 2023-07-18 22:15:27 · 997 阅读 · 0 评论 -
GO语言reflect
GO语言中参数为空接口,下面这种写法:原创 2023-07-18 19:38:51 · 74 阅读 · 0 评论 -
GO语言类型系统,接口,类型断言
每种类型都有对应的类型元数据,而类型定义的方法通过类型元数据找到。注意:别名是别名 ,自定义类型是自定义类型。原创 2023-07-18 14:53:32 · 193 阅读 · 0 评论 -
GO语言方法
本质 方法表达式和方法变量都是funcval。原创 2023-07-18 00:18:32 · 72 阅读 · 0 评论 -
GO语言闭包
函数的指令在编译期间生产,但是function value并不直接指向函数指令入口,而是指向runtime.funcval结构体。这个结构体只有一个地址,就是函数指令的入口地址。闭包:1 必须在函数外部定义,但在函数内部自由调用的变量。2,脱离形成闭包的上下文,也能照常运行。指向funcval,用一个二级指针来调用,这是为了解决闭包问题。其中,GO语言通过寄存器DX得到funcval结构体地址。闭包导致局部变量逃逸到堆。原创 2023-07-17 23:34:45 · 131 阅读 · 0 评论 -
GO语言slice
3,各种语言从OS上提前申请内存,匹配GO规则的内存。2,预估容量后*字节数 = 所需的内存。以及存取的元素是可以安全读写的。原创 2023-07-17 21:48:36 · 158 阅读 · 0 评论 -
GO语言String
String GO语言认为不可以修改。若想要改,可以重新复制,或者改为([]byte)类型。一个String: data+len(字节数)原创 2023-07-17 21:36:03 · 64 阅读 · 0 评论 -
深入理解GO语言垃圾回收全流程
GO语言引入辅助标记,辅助清扫,系统驻留内存存储,混合写屏障等策略保证能快速执行垃圾回收而且不影响用户协程,默认下,内存达到上一次GC标记内存的2倍后触发回收。并发阶段目标是消耗25%的CPU后台标记协程,清扫阶段,GO语言采用懒清扫策略。并留1%CPU执行系统驻留内存清除。原创 2023-05-07 23:33:14 · 723 阅读 · 0 评论 -
Go语言内存模型
栈内存(协程栈,调用栈)GO的协程栈位于GO的堆内存上。GO的堆内存在操作系统的虚拟内存上。协程栈的作用:1 协程执行路径。2 局部变量。3 函数传参。4 函数返回值。sum函数执行完后,返回,执行print。这是开辟print的栈。协程栈不够用怎么办?1,局部变量太多,2 栈桢太多。逃逸分析:原因:1,不是所有变量都能放在协程栈上 2,栈桢回收后,继续使用原来的变量。3,太大的变量。触发情形:1, 指针逃逸,2 空接口逃逸。3 大变量逃逸。原创 2023-04-02 15:27:59 · 463 阅读 · 0 评论 -
深入理解Go语言并发控制
数据争用是并发系统中最常见且最难调试的错误类型之一。原创 2023-05-04 23:16:15 · 233 阅读 · 0 评论 -
深入理解通道与协程间通信
CSP(communicating sequential processes,通信顺序进程)用于描述并发系统中交互模式的形式化语言,其通过通道传递消息。原创 2023-04-30 12:09:17 · 108 阅读 · 0 评论 -
深度理解协程设计与调度原理
我们发现这个过程中第三步程序注册的信号函数是一个新的函数,于是G O语言巧妙利用这个注册的函数设置为修改原程序中的rsp,rip寄存器的值,从而内核态放回到第五步,是一个新的函数。函数调用是一个比较安全的检查点,这时,函数切换调用g0,取消G和M的绑定关系,将G设置为running并放入全局队列,开启新一轮调度。在实际执行系统调用之前,会保存G的执行环境,并解除P与M的绑定。系统调用之后,会由于。当寻找可用的M时,需要先在M的空闲列表中查找是否有闲置的M,如果没有,则向操作系统申请一个新的M,即线程。原创 2023-04-29 21:49:47 · 203 阅读 · 0 评论 -
GO语言GMP模型
G:goroutine协程。P:processor处理器。起承上启下的作用,对于G来说是处理器,对于M来说用于屏蔽对G的调度,内存控制等逻辑。M:thread线程。原创 2023-04-25 22:26:32 · 334 阅读 · 1 评论 -
Go语言垃圾回收机制
首先将根对象标记为灰色,加入灰色集合,垃圾搜集器取出一个灰色对象,将其标记为黑色,并将其指向的对象标记为灰色,加入灰色集合。那么白色对象即可需要清理的对象,而黑色对象均为根可达的对象,不能被清理。为了解决这个问题,Go 使用了内存屏障技术,它是在用户程序读取对象、创建新对象以及更新对象指针时执行的一段代码,类似于一个钩子。正常情况下,D 对象最终会被标记为黑色,不应被回收。标记清除算法的一大问题是在标记期间,需要暂停程序(Stop the world,STW),标记结束之后,用户程序才可以继续执行。原创 2023-04-02 15:32:04 · 462 阅读 · 0 评论 -
Go语言网络模型
传入socket的fd, pollDesc指针,pollDesc指针是socket相关详细信息,pollDesc指针记录了哪个 协程休眠等待这个socket,将socket可读可写断开事件注册到epoll中。当netpoll发现socket可读写时,查看对应的g 或 wg,若为协程地址则返回协程地址,调度器开始调度这个协程。poll_runtime_pollOpen()在pollCache链表中分配一个pollDesc,初始化pollDesc(用于监听Socket),调用netpollopen()。原创 2023-04-02 15:31:09 · 163 阅读 · 0 评论 -
Go语言channel
i,ok<-c转化为runtime.chanrecv2()。3,休眠等待(无缓存,把自己包装成sudog,sudog放入sendq队列,休眠解锁。2,放入缓存(没有G在休眠等待,但是有缓存,则获取缓存地址,存入数据,维护索引)判断有G在发送队列等待进入recv(),channel不为空,取走数据,唤醒G。1,直接发送(发送之前已经有协程在休眠等待数据,此时缓存肯定是空的)没有G在发送等待,缓存为空,自己包装sudog 放入等待队列休眠。3,模块解藕,增强拓展性和可维护性。,直接从G 拷贝过来唤醒G。原创 2023-04-02 15:27:39 · 70 阅读 · 0 评论 -
Go语言map模型
Go 语言采用的是哈希查找表,并且使用链表解决哈希冲突。type hmap struct { // 元素个数,调用 len(map) 时,直接返回此值 count int flags uint8 // buckets 的对数 log_2 B uint8 // overflow 的 bucket 近似数 noverflow uint16 // 计算 key 的哈希的时候会传入哈希函数 hash0原创 2023-04-02 15:25:57 · 121 阅读 · 0 评论 -
goland分段锁
解决方法是:我们注意到哈希表的长度远少于可能的键的数量,反过来说多个键可以共用一个哈希槽。解决这个问题的方式: 我们可以要求有协程都按照相同顺序加锁,若两个协程都想获得键a和键b的锁,那么必须先获取键a的锁后获取键b的锁,这样就可以避免循环等待。在锁定多个key时需要注意,若协程A持有键a的锁试图获得键b的锁,此时协程B持有键b的锁试图获得键a的锁则会形成死锁。2,命令当且仅当所有给定键都不存在时所有给定键设置值, 因此我们需要锁定所有给定的键直到完成所有键的检查和设置。原创 2023-03-19 16:25:15 · 133 阅读 · 0 评论 -
GO语言空结构体
go 里的空结构体可以用来做什么事struct{}不占据任何内存空间,地址为 runtime.zerobase ,大小为 0 ,不占内存。因为空结构体只是占位符。它宽度是特殊的为0,这是 Go 编译器在内存分配时做的优化项,当发现 宽度size 为 0 时,会直接返回变量 zerobase 的引用,该变量是所有 0 字节的基准地址,不占据任何宽度。一般有Go 语言标准库没有提供 Set 的实现,通常使用 map 来代替。事实上,对于集合来说,只需要 map 的键,而不需要值。原创 2023-04-02 15:21:40 · 179 阅读 · 0 评论