1. GOMAXPROCS 设置
- 原理:
GOMAXPROCS
用于设置 Go 程序能够并行使用的操作系统线程数。默认情况下,GOMAXPROCS
的值等于 CPU 的核心数。通过合理设置 GOMAXPROCS
,可以充分利用多核 CPU 的性能。
- 优化策略:根据服务器的 CPU 核心数来设置
GOMAXPROCS
。如果是多核服务器,设置 GOMAXPROCS
为 CPU 核心数能让 Go 程序充分利用多核并行执行 goroutine。
- 代码示例:
package main
import (
"fmt"
"runtime"
)
func main() {
// 获取当前默认的 GOMAXPROCS
defaultProcs := runtime.GOMAXPROCS(0)
fmt.Printf("Default GOMAXPROCS: %d\n", defaultProcs)
// 设置 GOMAXPROCS 为 CPU 核心数
numCPU := runtime.NumCPU()
runtime.GOMAXPROCS(numCPU)
fmt.Printf("Set GOMAXPROCS to: %d\n", numCPU)
}
2. 任务的合理拆分
- 原理:将大的任务拆分成多个小的任务,每个小任务可以独立执行,这样可以充分利用 goroutine 的并发特性,提高整体的执行效率。
- 优化策略:分析业务逻辑,将可以并行执行的部分拆分成单独的 goroutine。例如,在处理网络请求时,如果请求处理过程中有多个独立的计算步骤,可以将每个步骤放在单独的 goroutine 中执行。
- 代码示例:
package main
import (
"fmt"
"sync"
)
// 模拟一个计算任务
func calculateTask(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Task %d is running\n", id)
// 模拟计算
for i := 0; i < 10000000; i++ {
_ = i * i
}
fmt.Printf("Task %d is done\n", id)
}
func main() {
var wg sync.WaitGroup
numTasks := 4
for i := 0; i < numTasks; i++ {
wg.Add(1)
go calculateTask(i, &wg)
}
wg.Wait()
fmt.Println("All tasks are done")
}
3. 调度器的扩展
- 原理:Go 的调度器(Goroutine Scheduler)负责管理和调度 goroutine 的执行。在高并发场景下,默认的调度器可能无法满足需求,需要进行扩展或优化。
- 优化策略:
- 使用工作池(Worker Pool)模式:创建一个固定数量的 goroutine 池,每个 goroutine 作为一个工作者,从任务队列中获取任务并执行。这样可以避免频繁创建和销毁 goroutine 的开销。
- 基于优先级的调度:根据任务的优先级,将高优先级的任务优先调度执行。可以通过自定义调度器或者在任务队列中进行优先级排序来实现。
- 代码示例(工作池模式):
package main
import (
"fmt"
"sync"
)
// 任务结构体
type Task struct {
id int
}
// 工作者函数
func worker(id int, taskChan <-chan Task, wg *sync.WaitGroup) {
defer wg.Done()
for task := range taskChan {
fmt.Printf("Worker %d is processing task %d\n", id, task.id)
// 模拟任务处理
for i := 0; i < 10000000; i++ {
_ = i * i
}
fmt.Printf("Worker %d has processed task %d\n", id, task.id)
}
}
func main() {
var wg sync.WaitGroup
numWorkers := 3
taskChan := make(chan Task, 10)
// 创建工作者
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go worker(i, taskChan, &wg)
}
// 添加任务
for i := 0; i < 5; i++ {
taskChan <- Task{id: i}
}
close(taskChan)
wg.Wait()
fmt.Println("All tasks are processed")
}