golang查看,golang查看版本

本文目錄一覽:

golang性能測試框架k6源碼分析

k6是新興的性能測試框架,比肩jmeter,另外測試腳本使用js,更加適合自動化的架構。

k6啟動的框架是使用golang的cli標準框架cobra,入口函數

進入cobra框架後,我們直接查看getRunCmd,這個是命令run的入口,主要工作都是從這裡開始。

重點關注初始化Runner,這個是通過js腳本,使用goja庫解析後,生成的實際執行單元。

進入js目錄,查看Runner的結構,runner.go

Runner有一些配置屬性,另外還有方法,方法用lib.Runner的介面進行規範。

Runner有一個NewVU方法,裡面定義了連接參數,實現api測試

返回主函數,在初始化完成Runner後,啟動調度器,以及做結果收集

最終封裝成一個engine

啟動測試

golang 查看結構體是否有某個屬性

package main

import (

    “reflect”

)

type User struct {

    ID int

    Name string

}

func main() {

    user := User{}

    t := reflect.TypeOf(user)

    if _, ok := t.FieldByName(“Name”); ok {

        println(“存在”)

    } else {

        println(“不存在”)

    }

}

【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 的核上執行

模型圖:

避免頻繁的創建、銷毀線程,而是對線程的復用。

1)work stealing機制

  當本線程無可運行的G時,嘗試從其他線程綁定的P偷取G,而不是銷毀線程。

2)hand off機制

  當本線程M0因為G0進行系統調用阻塞時,線程釋放綁定的P,把P轉移給其他空閑的線程執行。進而某個空閑的M1獲取P,繼續執行P隊列中剩下的G。而M0由於陷入系統調用而進被阻塞,M1接替M0的工作,只要P不空閑,就可以保證充分利用CPU。M1的來源有可能是M的緩存池,也可能是新建的。當G0系統調用結束後,根據M0是否能獲取到P,將會將G0做不同的處理:

如果有空閑的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的隊列,一個是局部調度器P的本地隊列、一個是全局G隊列。新創建的G會先保存在P的本地隊列中,如果P的本地隊列已經滿了就會保存在全局的隊列中;處理器本地隊列是一個使用數組構成的環形鏈表,它最多可以存儲 256 個待執行任務。

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:

用戶態阻塞/喚醒

當goroutine因為channel操作或者network I/O而阻塞時(實際上golang已經用netpoller實現了goroutine網路I/O阻塞不會導致M被阻塞,僅阻塞G,這裡僅僅是舉個栗子),對應的G會被放置到某個wait隊列(如channel的waitq),該G的狀態由_Gruning變為_Gwaitting,而M會跳過該G嘗試獲取並執行下一個G,如果此時沒有可運行的G供M運行,那麼M將解綁P,並進入sleep狀態;當阻塞的G被另一端的G2喚醒時(比如channel的可讀/寫通知),G被標記為,嘗試加入G2所在P的runnext(runnext是線程下一個需要執行的 Goroutine。), 然後再是P的本地隊列和全局隊列。

系統調用阻塞

當M執行某一個G時候如果發生了阻塞操作,M會阻塞,如果當前有一些G在執行,調度器會把這個線程M從P中摘除,然後再創建一個新的操作系統的線程(如果有空閑的線程可用就復用空閑線程)來服務於這個P。當M系統調用結束時候,這個G會嘗試獲取一個空閑的P執行,並放入到這個P的本地隊列。如果獲取不到P,那麼這個線程M變成休眠狀態, 加入到空閑線程中,然後這個G會被放入全局隊列中。

隊列輪轉

可見每個P維護著一個包含G的隊列,不考慮G進入系統調用或IO操作的情況下,P周期性的將G調度到M中執行,執行一小段時間,將上下文保存下來,然後將G放到隊列尾部,然後從隊列中重新取出一個G進行調度。

除了每個P維護的G隊列以外,還有一個全局的隊列,每個P會周期性地查看全局隊列中是否有G待運行並將其調度到M中執行,全局隊列中G的來源,主要有從系統調用中恢復的G。之所以P會周期性地查看全局隊列,也是為了防止全局隊列中的G被餓死。

除了每個P維護的G隊列以外,還有一個全局的隊列,每個P會周期性地查看全局隊列中是否有G待運行並將其調度到M中執行,全局隊列中G的來源,主要有從系統調用中恢復的G。之所以P會周期性地查看全局隊列,也是為了防止全局隊列中的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 模型的設計者的文檔或直接看源碼

參考: ()

()

golang安裝到mac上後怎麼看文件夾

找到蘋果電腦軟體安裝目錄方式:

方法一:

1、在系統的 Dock 欄中,找到一個叫住 Launchpad 的圖標;

2、接著就可以看到當前 Mac 中所有的應用程序了;

方法二:

1、除了上面的方法以外,你還可以點擊打開 Dock 欄中的 Finder 應用;

2、隨後在 Finder 窗口中,點擊左側的「應用程序」欄目;

3、接著就可以看到當前 Mac 上的所有應用程序了;

/

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/236477.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:00
下一篇 2024-12-12 12:00

相關推薦

  • Git secbit:一種新型的安全Git版本

    Git secbit是一種新型的安全Git版本,它在保持Git原有功能的同時,針對Git存在的安全漏洞做出了很大的改進。下面我們將從多個方面對Git secbit做詳細地闡述。 一…

    編程 2025-04-29
  • 使用Golang調用Python

    在現代軟體開發中,多種編程語言的協作是相當普遍的。其中一種使用場景是Golang調用Python,這使得在使用Python庫的同時,可以利用Golang的高性能和強大並發能力。這篇…

    編程 2025-04-29
  • 使用Golang創建黑色背景圖片的方法

    本文將從多個方面介紹使用Golang創建黑色背景圖片的方法。 一、安裝必要的代碼庫和工具 在開始創建黑色背景圖片之前,我們需要先安裝必要的代碼庫和工具: go get -u git…

    編程 2025-04-29
  • 如何將Java項目分成Modules並使用Git進行版本控制

    本文將向您展示如何將Java項目分成模塊,並使用Git對它們進行版本控制。分割Java項目可以使其更容易維護和拓展。Git版本控制還可以讓您跟蹤項目的發展並協作開發。 一、為什麼要…

    編程 2025-04-28
  • Python的版本演變

    Python是一門非常流行的編程語言,它有著簡潔、易讀、易寫的特點。自1991年由Guido van Rossum發明以來,Python已經發展成為一個成熟的編程語言,擁有多個版本…

    編程 2025-04-28
  • librosa版本用法介紹

    librosa是一個用於音頻信號處理的python庫,具有多種處理音頻的功能。在librosa庫中,版本號非常重要,在不同的版本中可能會存在一些差異。本文將圍繞librosa的版本…

    編程 2025-04-28
  • Java多版本支持實現方式

    本文將從以下幾個方面闡述如何實現Java多版本支持,並給出可行的代碼示例。 一、多版本Java環境概述 Java是一門跨平台的編程語言,但是在不同的應用場景下,可能需要使用不同版本…

    編程 2025-04-27
  • Taro3.5.11版本微信小程序端v-html依然無法解析video為中心的問題解決方案

    該問題的解決是通過使用 Taro3.5.11 版本自定義組件進行處理,具體解決方案如下: 一、自定義組件 首先,我們需要創建一個自定義組件 VideoComponent,該組件的主…

    編程 2025-04-27
  • 利用SeaweedFS版本進行大規模文件存儲與分配

    SeaweedFS是一個基於Go語言開發的分散式文件系統,它是一種高可用、高擴展性、高效率的解決方案。通過利用SeaweedFS版本,我們可以方便地實現大規模文件的存儲與分配。 一…

    編程 2025-04-27
  • Python多版本共存Ubuntu

    本文將介紹如何在Ubuntu系統中完美地編譯、安裝、配置多個Python版本,並且讓它們共存,以利於不同的Python應用程序的開發和執行。 一、安裝多個Python版本 Ubun…

    編程 2025-04-27

發表回復

登錄後才能評論