Go语言基础之runtime包
文章引用自
Golang中runtime的使用
runtime调度器是非常有用的东西,关于runtime包几个方法:
Gosched:让当前线程让出cpu以让其他线程运行,它不会挂起当前线程,因此当前线程未来会继续执行
NumCPU:返回当前系统的CPU核数量
GOMAXPROCS:设置最大的可同时使用的CPU核数
Goexit:退出当前goroutine(但是defer语句会照常执行)
NumGoroutine:返回真该执行和排队的任务总数
GOOS:目标操作系统
- GOROOT:返回本机的GO路径
package main import "fmt"
import "runtime" func main() {
fmt.Println("cpus:", runtime.NumCPU()) // 返回当前系统的CPU核数量
fmt.Println("goroot:", runtime.GOROOT()) //
fmt.Println("NumGoroutine:", runtime.NumGoroutine()) // 返回真该执行和排队的任务总数
fmt.Println("archive:", runtime.GOOS) // 目标操作系统
} 运行结果
cpus: 12
goroot: /usr/local/go
NumGoroutine: 1
archive: darwin
GOMAXPROCS
// 修改最大可同时使用CPU核数
Golang默认所有任务都运行在一个cpu核里,如果要在goroutine中使用多核,可以使用runtime.GOMAXPROCS函数修改,当参数小于1时使用默认值。
package main
import "fmt"
import "runtime"
import "time" func init(){
runtime.GOMAXPROCS(4) // 修改最大可同时使用CPU核数
} func main(){
t := time.Now().Nanosecond()
for i:=0;i<100000;i++{
fmt.Println(i*i*i*i)
}
t2 := time.Now().Nanosecond()
fmt.Println(t2-t)
}
Gosched
// 让当前线程让出cpu以让其他线程运行,它不会挂起当前线程,因此当前线程未来会继续执行
这个函数的作用是让当前goroutine让出CPU,当一个goroutine发生阻塞,Go会自动地把与该goroutine出于同一系统线程的其他goroutine转移到另一个系统线程上去,使得这些goroutine不阻塞。
package main import (
"fmt"
"runtime"
) func init() {
runtime.GOMAXPROCS(1) //使用单核
} func main() {
exit := make(chan int)
go func() {
defer close(exit)
go func() {
fmt.Println("b")
}()
}() for i := 0; i < 4; i++ {
fmt.Println("a:", i) if i == 1 {
runtime.Gosched() //切换任务
}
}
<-exit
}
在windows系统上,结果为:
a: 0
a: 1
a: 2
a: 3
切换成多核,每次运行的结果都不一样:
package main import (
"fmt"
"runtime"
) func main() {
runtime.GOMAXPROCS(4)
exit := make(chan int)
go func() {
defer close(exit)
go func() {
fmt.Println("b")
}()
}() for i := 0; i < 10; i++ {
fmt.Println("a:", i) if i == 4 {
runtime.Gosched() //切换任务
}
}
<-exit
}
总结:多核比较适合那种CPU密集型程序,如果是IO密集型使用多核会增加CPU切换的成本。
GOMAXPROCS和sync配合使用
sync.WaitGroup只有三个方法,Add(),Done()和Wait()。其中Done()是Add(-1)的别名。简单来说,使用Add()添加计数,Done()减少一个计数,计数不为0,阻塞Wait()的运行。
package main import (
"runtime"
"sync"
"fmt"
) func main(){
runtime.GOMAXPROCS(2)
var wg sync.WaitGroup
wg.Add(2)
fmt.Printf("Starting go routines")
go func(){
defer wg.Done()
for char := 'a';char<'a'+26;char++{
fmt.Printf("%c",char)
}
}()
go func() {
defer wg.Done()
for number := 1;number<27;number++{
fmt.Printf("%d",number)
}
}() fmt.Println("\nWaiting to finish")
wg.Wait()
fmt.Println("\n terminating program")
}
运行结果:
Starting go routines
Waiting to finish
1234567891011121314151617181920212223242526abcdefghijklmnopqrstuvwxyz
terminating program
总结:首先是wg.Add(2)计数为2,阻塞wg.Wait()的运行,然后是wg.Done()减少计数到0,放开wg.Wait()的运行。
runtime.Caller
Caller 方法反应的是堆栈信息中某堆栈帧所在文件的绝对路径和语句所在文件的行数。而 skip 表示的是从下往上数第几个堆栈帧。如果要打印全部堆栈信息可以直接使用 debug.PrintStack()
来实现。
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
参数:skip是要提升的堆栈帧数,0-当前函数,1-上一层函数,....
返回值:
pc是uintptr这个返回的是函数指针
file是函数所在文件名目录
line所在行号
ok 是否可以获取到信息
示例:
我们分别打印skip为0-3的相关信息
package main import (
"fmt"
"runtime"
) func main() {
for i := 0 ; i< 4; i++ {
test(i)
}
} func test(skip int) {
call(skip)
} func call(skip int) {
pc,file,line,ok := runtime.Caller(skip)
pcName := runtime.FuncForPC(pc).Name() //获取函数名
fmt.Println(fmt.Sprintf("%v %s %d %t %s",pc,file,line,ok,pcName))
返回
17412399 /Users/songzhibin/go/src/Songzhibin/study/3.go 19 true main.call
17412303 /Users/songzhibin/go/src/Songzhibin/study/3.go 15 true main.test
17412294 /Users/songzhibin/go/src/Songzhibin/study/3.go 10 true main.main
16953069 /usr/local/go/src/runtime/proc.go 203 true runtime.main
Go语言基础之runtime包的更多相关文章
- Go语言基础之time包
Go语言基础之time包 时间和日期是我们编程中经常会用到的,本文主要介绍了Go语言内置的time包的基本用法. Go语言中导入包 Go语言中使用import关键字导入包,包的名字使用双引号(”)包裹 ...
- Go语言基础之Path包与FilePath包
文章引用自 path包的使用 package main; import ( "fmt" "path" ) //go语言path包的学习 func main() ...
- go语言基础之导入包的常用方法
1.导入包 示例: 法一 package main //导入包,必须使用,否则编译不过 import "fmt" import "os" func main() ...
- Go语言基础之包
Go语言基础之包 在工程化的Go语言开发项目中,Go语言的源码复用是建立在包(package)基础之上的.本文介绍了Go语言中如何定义包.如何导出包的内容及如何导入其他包. Go语言的包(packag ...
- Go语言基础包之net/http
Go语言基础包之net/http Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现. net/http介绍 Go语言内置的net/http包提供了HTTP客户端和服务端的 ...
- GO学习-(15) Go语言基础之包
Go语言基础之包 在工程化的Go语言开发项目中,Go语言的源码复用是建立在包(package)基础之上的.本文介绍了Go语言中如何定义包.如何导出包的内容及如何导入其他包. Go语言的包(packag ...
- [06 Go语言基础-包]
[06 Go语言基础-包] 包 什么是包,为什么使用包? 到目前为止,我们看到的 Go 程序都只有一个文件,文件里包含一个 main 函数和几个其他的函数.在实际中,这种把所有源代码编写在一个文件的方 ...
- go语言之进阶篇runtime包中 Gosched Goexit GOMAXPROCS的使用
一.runtime包 1.Gosched的使用 runtime.Gosched() 用于让出CPU时间片,让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢 ...
- Golang 入门系列(三)Go语言基础知识汇总
前面已经了 Go 环境的配置和初学Go时,容易遇到的坑,大家可以请查看前面的文章 https://www.cnblogs.com/zhangweizhong/category/1275863.html ...
随机推荐
- CQYZOJ P1392 拔河问题
题目\(1\) Description 一个学校举行拔河比赛,所有的人被分成了两组,每个人必须(且只能够)在其中的一组,且两个组内的所有人体重加起来尽可能地接近. Input 第\(1\)行是一个\( ...
- VNCserver 安装 及 oracle过程总结
一.安装桌面系统 1.命令 yum grouplist ---列举系统中以组安装的包(组安装的包会包括很多,组安装一下就就可以安装很多附在的包.) 2. yum groupinstall &qu ...
- 5G套餐资费或为199元至599元,高昂价格会阻碍大众使用热情吗?
近段时间,运营商各种谜一般的操作让其走上舆论的风口浪尖,成为人们口诛笔伐的对象.比如在前段时间,运营商相继宣布要取消"达量降速版畅享套餐",对用户的权益造成巨大冲击,引发了网络热议 ...
- python3 win 建立虚拟环境(virtualenv)
1.安装virtualenv pip3 install virtualenv 2.进入即将创建虚拟环境的目录 cd xxxx 3.创建虚拟环境 py -3 -m venv testxunihua 4. ...
- Codeforces Round #609 (Div. 2) A-E简要题解
contest链接:https://codeforces.com/contest/1269 A. Equation 题意:输入一个整数,找到一个a,一个b,使得a-b=n,切a,b都是合数 思路:合数 ...
- 如何修改C# winform程序图标
以Visual Studio 2012 C# Winform程序为例 一.程序内部显示图标的修改方法 在窗体的属性窗口找到icon属性,设置成已经准备好的ico格式的文件,效果如下 二.程序外部显示图 ...
- Java的多态-进阶
Java的多态——进阶 总括 Parent p = new Child(); 反之,Child() c = new Parent(); 会报错. 当使用多态方式调用方法时,首先检查父类中是否有该方法. ...
- python下matplotlib、numpy、pandas联合作图逐步深入分析
1.代码1: from pandas import Series,DataFrame from numpy.random import randn import numpy as np import ...
- 文件操作_python
一.基础文件操作读写 1.建立文件对象两种建立对象方式: f=open('文件1','r',encoding='utf8') with open('文件1','r',encoding='utf8') ...
- analog filter
理想的filter如下: 但是实际的filter如下: 在实际应用中,我们更多的是用Fo和Q这两个parameter来design analog filter. Low-Pass Filter tra ...