当前位置:首页 > 正文

go语言量化分析_golang 量化

更新时间:2025-04-16 17:38 阅读量:37

【golang详解】go语言GMP(GPM)原理和调度

Goroutine调度是一个很复杂的机制,下面尝试用简单的语言描述一下Goroutine调度机制,想要对其有更深入的了解可以去研读一下源码.

首先介绍一下GMP什么意思:

G ----------- goroutine: 即Go协程,每个go关键字都会创建一个协程.

M ---------- thread内核级线程,所有的G都要放在M上才能运行.

P ----------- processor处理器,调度G到M上,其维护了一个队列,存储了所有需要它来调度的G.

Goroutine 调度器P和 OS 调度器是通过 M 结合起来的,每个 M 都代表了 1 个内核线程,OS 调度器负责把内核线程分配到 CPU 的核上执行

模型图:

避免频繁的创建、销毁线程,而是对线程的复用.

①.)work stealing机制

? 当本线程无可运行的G时,尝试从其他线程绑定的P偷取G,而不是销毁线程.

如果有空闲的P,则获取一个P,继续执行G0.

如果没有空闲的P,则将G0放入全局队列,等待被其他的P调度.然后M0将进入缓存池睡眠.

如下图

GOMAXPROCS设置P的数量,最多有GOMAXPROCS个线程分布在多个CPU上同时运行

在Go中一个goroutine最多占用CPU 10ms,防止其他goroutine被饿死.

具体可以去看另一篇文章

【Golang详解】go语言调度机制 抢占式调度

当创建一个新的G之后优先加入本地队列,如果本地队列满了,会将本地队列的G移动到全局队列里面,当M执行work stealing从其他P偷不到G时,它可以从全局G队列获取G.

协程经历过程

我们创建一个协程 go func()经历过程如下图:

说明:

G只能运行在M中,一个M必须持有一个P,M与P是1:1的关系.M会从P的本地队列弹出一个可执行状态的G来执行,如果P的本地队列为空,就会想其他的MP组合偷取一个可执行的G来执行;

一个M调度G执行的过程是一个循环机制;会一直从本地队列或全局队列中获取G

上面说到P的个数默认等于CPU核数,每个M必须持有一个P才可以执行G,一般情况下M的个数会略大于P的个数,这多出来的M将会在G产生系统调用时发挥作用.类似线程池,Go也提供一个M的池子,需要时从池子中获取,用完放回池子,不够用时就再创建一个.

work-stealing调度算法:当M执行完了当前P的本地队列队列里的所有G后,P也不会就这么在那躺尸啥都不干,它会先尝试从全局队列队列寻找G来执行,如果全局队列为空,它会随机挑选另外一个P,从它的队列里中拿走一半的G到自己的队列中执行.

如果一切正常,调度器会以上述的那种方式顺畅地运行,但这个世界没这么美好,总有意外发生,以下分析goroutine在两种例外情况下的行为.

Go runtime会在下面的goroutine被阻塞的情况下运行另外一个goroutine:

用户态阻塞/唤醒

系统调用阻塞

当M执行某一个G时候如果发生了阻塞操作,M会阻塞,如果当前有一些G在执行,调度器会把这个线程M从P中摘除,然后再创建一个新的操作系统的线程(如果有空闲的线程可用就复用空闲线程)来服务于这个P.当M系统调用结束时候,这个G会尝试获取一个空闲的P执行,并放入到这个P的本地队列.如果获取不到P,那么这个线程M变成休眠状态, 加入到空闲线程中,然后这个G会被放入全局队列中.

队列轮转

可见每个P维护着一个包含G的队列,不考虑G进入系统调用或IO操作的情况下,P周期性的将G调度到M中执行,执行一小段时间,将上下文保存下来,然后将G放到队列尾部,然后从队列中重新取出一个G进行调度.

M0

M0是启动程序后的编号为0的主线程,这个M对应的实例会在全局变量rutime.m0中,不需要在heap上分配,M0负责执行初始化操作和启动第一个G,在之后M0就和其他的M一样了

G0

G0是每次启动一个M都会第一个创建的goroutine,G0仅用于负责调度G,G0不指向任何可执行的函数,每个M都会有一个自己的G0,在调度或系统调用时会使用G0的栈空间,全局变量的G0是M0的G0

一个G由于调度被中断,此后如何恢复?

中断的时候将寄存器里的栈信息,保存到自己的G对象里面.当再次轮到自己执行时,将自己保存的栈信息复制到寄存器里面,这样就接着上次之后运行了.

我这里只是根据自己的理解进行了简单的介绍,想要详细了解有关GMP的底层原理可以去看Go调度器 G-P-M 模型的设计者的文档或直接看源码

参考: ()

()

六星教育:Python和go语言都很火,我要怎么选?

Go语言(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言.Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态以及 CSP-style 并发计算.

python是一种广泛使用的具有动态语义的解释型,面向对象的高级编程语言.

Python是一种面向对象的高级编程语言,具有集成的动态语义,主要用于Web和应用程序开发.它在快速应用程序开发领域极具吸引力,因为它提供动态类型和动态绑定选项.

Python是一种解释型语言,这意味着用Python编写的程序不需要事先编译就可以运行,从而可以轻松地测试小段代码并使用Python编写的代码更容易在平台之间移动.

python和go语言的区别:

①.、语法

Python的语法使用缩进来指示代码块.Go的语法基于打开和关闭括号.

Python是一种基于面向对象编程的多范式,命令式和函数式编程语言.它坚持这样一种观点,即如果一种语言在某些情境中表现出某种特定的方式,理想情况下它应该在所有情境中都有相似的作用.但是,它又不是纯粹的OOP语言,它不支持强封装,这是OOP的主要原则之一.

Go是一种基于并发编程范式的过程编程语言,它与C具有表面相似性.实际上,Go更像是C的更新版本.

Python没有提供内置的并发机制,而Go有内置的并发机制.

Python是动态类型语言,而Go是一种静态类型语言,它实际上有助于在编译时捕获错误,这可以进一步减少生产后期的严重错误.

Python是一种强类型语言,它是经过编译的,所以呢增加了一层安全性.Go具有分配给每个变量的类型,所以呢,它提供了安全性.但是,如果发生任何错误,用户需要自己运行整个代码.

Go允许程序员在很大程度上管理内存.而,Python中的内存管理完全自动化并由Python VM管理;它不允许程序员对内存管理负责.

与Go相比,Python提供的库数量要大得多.然而,Go仍然是新的,并且还没有取得很大进展.

Go的速度远远超过Python.

Python与Golang对比:

①.、特点:

Golang

①静态强类型、编译型、并发型

静态类型语言,但是有动态语言的感觉.(静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高)

可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了.

语言层面支持并发,这个就是Go最大的特色,天生的支持并发.Go就是基因里面支持的并发,可以充分地利用多核,很容易地使用并发.

②垃圾回收机制

内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC(内存垃圾回收机制)不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC.

③支持面向对象编程

有接口类型和实现类型的概念,但是用嵌入替代了继承.

④丰富的标准库

Go目前已经内置了大量的库,特别是网络库非常强大.

⑤内嵌C支持

Go里面也可以直接包含C代码,利用现有的丰富的C库

Python

①解释型语言

程序不需要在运行前编译,在运行程序的时候才翻译,专门的解释器负责在每个语句执行的时候解释程序代码.这样解释型语言每执行一次就要翻译一次,效率比较低.

②动态数据类型

③完全面向对象的语言

函数,模块,数字,字符串都是对象,在Python中,一切接对象

完全支持继承,重载,多重继承

④拥有强大的标准库

Python语言的核心只包含数字,字符串,列表,元祖,字典,集合,文件等常见类型和函数,而由Python标准库提供了系统管理,网络通信,文本处理,数据库接口,图形系统,XML处理等额外的功能.

⑤社区提供了大量第三方库

Python 社区提供了大量的第三方模块,使用方式与标准库类似.它们的功能覆盖 科学计算、人工智能、机器学习、Web 开发、数据库接口、图形系统 多个领域.

①网络编程

web应用,网络爬虫

②数据分析和机器学习

③自动化测试

④自动化运维

①服务器编程

处理日志、数据打包、虚拟机处理、文件系统等.

②分布式系统,数据库代理器等

③网络编程

④内存数据库

如google开发的groupcache,couchbase的部分组件.

⑥云平台

Go语言和Python学哪个好?

Python 可以很好地集成到企业级应用中,可用于机器语言和 AI 应用.Go 语言的特点表明它具备轻量级线程实现(Goroutine)、智能标准库、强大的内置安全性,且可使用最简语法进行编程.Go 在大部分案例中领先,被认为是 Python 的有效替代方案.开发者在选择编程语言时,应考虑开发项目的性质和规模,以及所需的技能组合.

放下个人偏见和喜好,从优点和功能的角度来评价两种语言.不管选择了哪种语言,Go 和 Python 都在持续演进.尽管在大多数情况下 Golang 可能是更好的选择,但Python语言也是不断更新迭代的.