图解Go语言GMP模型

news/2024/7/9 23:13:19 标签: golang, linux, postgresql

声明

非完全原创,大部分内容来自于学习其他人的理论。如果有侵权,请联系我,可以立即删除掉。

Linux进程的内存使用

在这里插入图片描述

CPU对内存的访问

  • CPU 上有个Memory Management Unit(MMU) 单元
  • CPU 把虚拟地址给MMU,MMU 去物理内存中查询页表,得到实际的物理地址
  • CPU 维护一份缓存Translation Lookaside Buffer(TLB),缓存虚拟地址和物理地址的映射关系
    在这里插入图片描述

进程切换开销

直接开销

  • 切换页表全局目录(PGD)
  • 切换内核态堆栈
  • 切换硬件上下文(进程恢复前,必须装入寄存器的数据统称为硬件上下文)
  • 刷新TLB
  • 系统调度器的代码执行

间接开销

  • CPU 缓存失效导致的进程需要到内存直接访问的IO 操作变多

线程切换开销

• 线程本质上只是一批共享资源的进程,线程切换本质上依然需要内核进行进程切换
• 一组线程因为共享内存资源,因此一个进程的所有线程共享虚拟地址空间,线程切换相比进程切换,主要节省了虚拟地址空间的切换

用户线程

无需内核帮助,应用程序在用户空间创建的可执行单元,创建销毁完全在用户态完成。
在这里插入图片描述

Goroutine

Go 语言基于GMP 模型实现用户态线程
• G:表示goroutine,每个goroutine 都有自己的栈空间,定时器,初始化的栈空间在2k 左右,空间会随着需求增长。
• M:抽象化代表内核线程,记录内核线程栈信息,当goroutine 调度到线程时,使用该goroutine 自己的栈信息。
• P:代表调度器,负责调度goroutine,维护一个本地goroutine 队列,M 从P 上获得goroutine 并执行,同时还负责部分内存的管理。
在这里插入图片描述

GMP对应关系

在这里插入图片描述

GMP模型细节

在这里插入图片描述

G的状态转换图

在这里插入图片描述

G 所处的位置

• 进程都有一个全局的G 队列
• 每个P 拥有自己的本地执行队列
• 有不在运行队列中的G

  • 处于channel 阻塞态的G 被放在sudog
  • 脱离P 绑定在M 上的G,如系统调用
  • 为了复用,执行结束进入P 的gFree 列表中的G

Goroutine 创建过程

获取或者创建新的Goroutine 结构体

  • 从处理器的gFree 列表中查找空闲的Goroutine
  • 如果不存在空闲的Goroutine,会通过runtime.malg 创建一个栈大小足够的新结构体

• 将函数传入的参数移到Goroutine 的栈上
• 更新Goroutine 调度相关的属性,更新状态为_Grunnable
• 返回的Goroutine 会存储到全局变量allgs 中

将Goroutine 放到运行队列上

• Goroutine 设置到处理器的runnext 作为下一个处理器执行的任务
• 当处理器的本地运行队列已经没有剩余空间时,就会把本地队列中的一部分Goroutine 和待加入的Goroutine通过runtime.runqputslow 添加到调度器持有的全局运行队列上

调度器行为

• 为了保证公平,当全局运行队列中有待执行的Goroutine 时,通过schedtick 保证有一定几率(1/61)会从全局的运行队列中查找对应的Goroutine
• 从处理器本地的运行队列中查找待执行的Goroutine
• 如果前两种方法都没有找到Goroutine,会通过runtime.findrunnable 进行阻塞地查找Goroutine

  • 从本地运行队列、全局运行队列中查找
  • 从网络轮询器中查找是否有Goroutine 等待运行
  • 通过runtime.runqsteal 尝试从其他随机的处理器中窃取待运行的Goroutine

http://www.niftyadmin.cn/n/795894.html

相关文章

前方高能!java同步回调和异步回调

常见resdis面试真题40道(含解析) 什么是 Redis?Redis 的数据类型?使用 Redis 有哪些好处?Redis 相比 Memcached 有哪些优势?Memcache 与 Redis 的区别都有哪些?Redis 是单进程单线程的?一个字…

超级详细的k8s入门教程

简介 kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 这个工具能通过两条指令完成一个kubernetes集群的部署&#xff1a; 创建一个 Master 节点&#xff1a;kubeadm init将一个 Node 节点加入到当前集群中&#xff1a;ubeadm join <Master节点的IP和端口…

spring boot 对某个接口进行次数限制,防刷。简易版。demo。

spring boot 对某个接口进行次数限制&#xff0c;防刷。简易版。demo。 一般的项目 如果没有做防刷 容易被人爆接口 或者就是说没有做token防刷过滤。 容易被人用正常的token刷接口。有些token非一次性。 用户登录之后生成token会有一个过期时间&#xff0c;但一般没有做频率检…

oppoJava面试题,最经典的HashMap图文详解

正文 一些看到我文章的朋友&#xff0c;问我怎么零基础Java“逆袭”&#xff0c;又怎么学好Java。 以下是我的一些经验总结吧&#xff1a; 1.制定好一下系统的学习规划&#xff0c;每天定量&#xff0c;学完什么知识点就掌握&#xff0c;能自己应用&#xff0c;而不是能看懂&a…

k8s部署tomcat+mysql服务

发布MySQL RC mysql-rc.yaml apiVersion: v1 kind: ReplicationController # 副本控制器RC metadata:name: mysql # RC的名称&#xff0c;全局唯一 spec:replicas: 1 # Pod副本的期待数量selector:app: mysql # 符合目标的pod拥有此标签template: # 根据此模板创建Pod的副本m…

Golang基础链表

package mainimport ("fmt" )// 最简单的链表 type LinkNode struct {Data int64NextNode *LinkNode }func main() {// 新的节点node : new(LinkNode)node.Data 1// 新的节点node1 : new(LinkNode)node1.Data 2node.NextNode node1 // node1 链接到 node 节点…

oppoJava面试题,腾讯Redis压轴笔记

一、对Kafka的认识 1.Kafka的基本概念 2.安装与配置 3.生产与消费 4.服务端参数配置 二、生产者 1.客户端开发 必要的参数配置消息的发送序列化分区器生产者拦截器 2.原理分析 整体架构元数据的更新 3.重要的生产者参数 三、消费者 1.消费者与消费组 2.客户端开发 必要的…

Golang循环链表

// 循环链表 type Ring struct {prev *Ring // 前驱节点next *Ring // 后驱节点Value interface{} // 数据 }// 初始化空的循环链表&#xff0c;前驱和后驱都指向自己&#xff0c;因为是循环的 func (r *Ring) Init() *Ring {r.next rr.prev rreturn r }// 创建…