【发布时间】:2014-12-18 17:41:42
【问题描述】:
我已经完成了简单的基准测试,哪一个在消息传递和共享值锁定方面效率更高。
首先,请检查下面的代码。
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)
}
}
wg.Wait()
elapsed := time.Since(start)
fmt.Println("Elapsed:", elapsed, "value:", sharedValue)
}
正如您已经注意到的,程序相对简单。 消息模式,通过消息传递增加sharedValue。在互斥模式下,它通过锁定增加sharedValue。
我曾尝试仅将一个频道用于消息模式并放弃了。我想这可能是不可能的,不是吗?
我的计算机有 2 个 Xeon CPU,每个 CPU 有 6 个内核。由于超线程,逻辑上可以使用 24 个内核。它的内存大小为 12G。
如果我使用任意数量的标志运行程序,互斥模式总是更快至少 2 倍(通常是 3 倍)。
好的,我可以理解管理渠道需要一定的成本。那么,如果我只考虑性能,是否有任何理由使用通道而不是互斥锁?另外,如果消息量很大,消息传递成本可以忽略吗?
【问题讨论】: