Go调度性能优化 - Golang调度器优化实战
调度器性能直接影响Go程序的并发性能。掌握调度优化技巧对于构建高性能Go应用至关重要。
📋 核心优化策略
优化要点总结
- GOMAXPROCS设置: 合理配置P的数量
- Goroutine池化: 复用goroutine减少创建开销
- 亲和性优化: 利用P的本地队列特性
- 负载均衡: 避免工作窃取开销
go
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
func main() {
fmt.Println("=== Go调度性能优化 ===")
// 1. GOMAXPROCS优化
fmt.Printf("\n--- GOMAXPROCS优化 ---\n")
cpus := runtime.NumCPU()
fmt.Printf("CPU核心数: %d\n", cpus)
// 对于CPU密集型任务,设置为CPU数量
runtime.GOMAXPROCS(cpus)
fmt.Printf("设置GOMAXPROCS: %d\n", cpus)
// 2. Goroutine池化
fmt.Printf("\n--- Goroutine池化 ---\n")
type WorkerPool struct {
tasks chan func()
workers int
wg sync.WaitGroup
}
func NewWorkerPool(workers int) *WorkerPool {
pool := &WorkerPool{
tasks: make(chan func(), workers*2),
workers: workers,
}
for i := 0; i < workers; i++ {
pool.wg.Add(1)
go pool.worker()
}
return pool
}
func (p *WorkerPool) worker() {
defer p.wg.Done()
for task := range p.tasks {
task()
}
}
func (p *WorkerPool) Submit(task func()) {
p.tasks <- task
}
func (p *WorkerPool) Close() {
close(p.tasks)
p.wg.Wait()
}
// 使用worker pool
pool := NewWorkerPool(runtime.NumCPU())
start := time.Now()
for i := 0; i < 10000; i++ {
id := i
pool.Submit(func() {
_ = id * 2
})
}
pool.Close()
fmt.Printf("Worker Pool完成10000任务,耗时: %v\n", time.Since(start))
// 3. 避免过度并发
fmt.Printf("\n--- 并发控制 ---\n")
sem := make(chan struct{}, 100) // 限制并发数为100
var wg sync.WaitGroup
start = time.Now()
for i := 0; i < 10000; i++ {
wg.Add(1)
sem <- struct{}{} // 获取信号量
go func(id int) {
defer func() {
<-sem // 释放信号量
wg.Done()
}()
_ = id * 2
}(i)
}
wg.Wait()
fmt.Printf("限流并发完成10000任务,耗时: %v\n", time.Since(start))
fmt.Printf("\n📋 优化建议:\n")
fmt.Printf("1. CPU密集: GOMAXPROCS = CPU核心数\n")
fmt.Printf("2. I/O密集: 可适当增加GOMAXPROCS\n")
fmt.Printf("3. 使用Worker Pool复用goroutine\n")
fmt.Printf("4. 限制并发数避免调度开销\n")
fmt.Printf("5. 批量处理减少goroutine创建\n")
}🎯 关键优化点
- GOMAXPROCS调优: 根据工作负载特性设置
- 池化复用: Worker Pool模式减少创建销毁
- 并发控制: 使用信号量限制goroutine数量
- 批量处理: 减少细粒度并发的调度开销
