Go中runtime.GOMAXPROCS的设置导致的性能问题

本文探讨了Go语言中并发与并行的概念区别及其实际应用。通过具体代码示例,展示了不同CPU核心数量对程序执行效率的影响,并分析了在IO密集型与CPU密集型任务中并行的优势与局限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        首先我们应该明确,并行和并发的区别,我之前文章中有详细的解释。概要说就是,并发一般都是被内核通过时间片或者中断来控制的,一旦遇到IO阻塞或者时间片用完,就会转移线程的使用权。单核不可能有并行,同一时间只能有一个任务在调度。

        Go中runtime.GOMAXPROCS可以设置多核执行任务。并行比较适合cpu计算密集型。如果IO密集型使用多核反而会增加cpu切换的成本。

 

需要特意说明一点是,你在测试并发的时候,往往会把一个函数写成死循环并做计算,你虽然这段函数用go关键词并发了,但是你会发现他无法执行后面的逻辑。你需要做的是配置多核,或者是time.Sleep()。  这是为什么 ? Golang是自己管理调整goroutine,如果你的一个func始终不释放资源,那么其他的goroutine不会去抢夺资源。 当然这样的场景只有在测试时候遇到,正常场景下不可能没有中断和堵塞的情况。 

 

那为何说设置的核心越多反而会降低性能?看下面代码:

package main

import(
	"fmt"
	"time"
	"runtime"
)

var quit chan int = make(chan int)

func loop(){
	for i:=0 ;i<10000; i++{
		fmt.Printf("%d\n", i)		
	}
	
	quit <- 0
}

func main(){
	fmt.Println(runtime.NumCPU()) // 默认CPU核心数
	time.Sleep(2*time.Second)
	a := 5000
	t0 := time.Now()      // 起点时间
	//runtime.GOMAXPROCS(1) // 设置执行使用的核心数
	
	for i:=1; i<= a; i++{
		go loop()
	}
	
	for i:=0; i< a; i++{
		<-quit
	}
	
	endTime := time.Since(t0) // 耗时
	fmt.Println("运行时间", endTime)
	
}

        首先说明我的电脑是8核ubuntu ,  其中runtime.GOMAXPROCS(1) 被注释, 得到的结果是 2m13s 。    

取消注释,使用一个核心执行此程序,得到的确实1m 20s。 (都是多次执行取平均值)。    

        此处还要注意点一点就是: Go默认执行使用的CPU核心数为系统CPU最大核心。

        有的码友可能觉得是channel的问题, 多个协程同时写入,带来的并发问题。其实不然,此处瓶颈在于fmt,

由于多个协程同时往stdout写入, 纵然前面执行再快,最后还是要单线程输出到屏幕,导致的性能问题,如果fmt换为其他操作,就可以显示出GOMAXPROCS的好处。

 

 

转载于:https://my.oschina.net/90design/blog/1837570

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值