Buffered channel、slice和mutex的简单性能测试

时间:2022-05-05
本文章向大家介绍Buffered channel、slice和mutex的简单性能测试,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
测试代码:
package main

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

const COUNT = 1000000

func bench1(ch chan int) time.Duration {
    t := time.Now()
    for i := 0; i < COUNT; i++ {
        ch <- i
    }
    var v int
    for i := 0; i < COUNT; i++ {
        v = <-ch
    }
    _ = v
    return time.Now().Sub(t)
}

func bench2(s []int) time.Duration {
    t := time.Now()
    for i := 0; i < COUNT; i++ {
        s[i] = i
    }
    var v int
    for i := 0; i < COUNT; i++ {
        v = s[i]
    }
    _ = v
    return time.Now().Sub(t)
}

func bench3(s []int, mutex *sync.Mutex) time.Duration {
    t := time.Now()
    for i := 0; i < COUNT; i++ {
        mutex.Lock()
        s[i] = i
        mutex.Unlock()
    }
    var v int
    for i := 0; i < COUNT; i++ {
        mutex.Lock()
        v = s[i]
        mutex.Unlock()
    }
    _ = v
    return time.Now().Sub(t)
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    ch := make(chan int, COUNT)
    s := make([]int, COUNT)
    var mutex sync.Mutex
    fmt.Println("channeltslicetmutex_slice")
    for i := 0; i < 10; i++ {
        fmt.Printf("%vt%vt%vn", bench1(ch), bench2(s), bench3(s, &mutex))
    }
}

测试环境

CPU: i7-3770

MEMORY: 32G

OS: ubuntu12.04 x86_64

GO VERSION: 1.0.3

输出:

channel

slice

mutex_slice

53.774ms

1.735ms

37.103ms

52.978ms

1.058ms

36.928ms

52.864ms

1.058ms

36.928ms

53.337ms

1.069ms

38.073ms

53.695ms

1.055ms

37.801ms

53.45ms

1.063ms

37.683ms

53.678ms

1.161ms

37.767ms

3.568ms

1.052ms

37.792ms

53.47ms

1.06ms

37.185ms

52.78ms

1.062ms

36.899ms

结论:

在没有竞争的情况下,缓冲信道比线程锁稍慢,但执行时间是直接对数组读写的40~50倍。

引申:

对于之前的提到的内存分配器,或者其他类型的资源分配器,如果频繁调用的话,还是限制在goroutine内存分配器更合适。应该尽量避免在goroutine间分配资源。当然,实际的性能调整应该基于profile定位性能瓶颈而不是单纯的想象。