我已经完成了简单的基准测试,在消息传递和共享值锁定中哪一个更有效。
首先,请检查下面的代码。
package main
import (
"flag"
"fmt"
"math/rand"
"runtime"
"sync"
"time"
)
type Request struct {
Id int
ResChan chan Response
}
type Response struct {
Id int
Value int
}
func main() {
procNum := flag.Int("proc", 1, "Number of processes to use")
clientNum := flag.Int("client", 1, "Number of clients")
mode := flag.String("mode", "message", "message or mutex")
flag.Parse()
if *procNum > runtime.NumCPU() {
*procNum = runtime.NumCPU()
}
fmt.Println("proc:", *procNum)
fmt.Println("client:", *clientNum)
fmt.Println("mode:", *mode)
runtime.GOMAXPROCS(*procNum)
rand.Seed(time.Now().UnixNano())
var wg sync.WaitGroup
sharedValue := 0
start := time.Now()
if *mode == "message" {
reqChan := make(chan Request) // increasing channel size does not change the result
go func() {
for {
req := <-reqChan
sharedValue++
req.ResChan <- Response{Id: req.Id, Value: sharedValue}
}
}()
for i := 0; i < *clientNum; i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
c := make(chan Response)
defer close(c)
id := rand.Int()
reqChan <- Request{Id: id, ResChan: c}
<-c
}(i)
}
} else if *mode == "mutex" {
mutex := &sync.Mutex{}
for i := 0; i < *clientNum; i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
mutex.Lock()
sharedValue++
mutex.Unlock()
}(i)
}
}
正如您已经注意到的,程序相对简单。在消息模式下,它通过消息传递增加 sharedValue。在互斥模式下,它通过锁定来增加sharedValue。
我曾尝试仅使用一个通道进行消息模式并放弃了。我想这可能是不可能的,不是吗?
我的电脑有 2 个 Xeon CPU,每个 CPU 有 6 个内核。由于超线程,逻辑上有 24 个内核可用。其内存大小为 12G。
如果我使用任意数量的标志运行程序,互斥模式总是至少快 2 倍(通常是 3 倍)。
好的,我可以理解管理渠道需要一定的成本。那么,如果我只考虑性能,是否有任何理由使用通道而不是互斥锁?另外,消息传递的成本是否可以被巨大的消息忽略?
FFIVE
慕妹3146593
相关分类