duandeng1824
2017-10-27 12:20
浏览 107
已采纳

Golang Goroutine添加并发时速度变慢

I am studying about golang and use of goroutine.
With this sample code, on my PC with 4 logical CPUs, I can't understand why I don't have any performance improvement.

If I add in concurrency, the time it takes to do tends to slow down by the original without concurrency.

2017/10/27 13:57:17 Starting 1 threads
2017/10/27 13:57:27 Id routine: 0  rate: 232.558140
2017/10/27 13:57:27 Current total rate was 232.56 K/s
2017/10/27 13:57:27 Starting 1 threads
2017/10/27 13:57:37 Id routine: 0  rate: 357.142857
2017/10/27 13:57:37 Current total rate was 357.14 K/s


2017/10/27 13:58:04 Starting 2 threads
2017/10/27 13:58:14 Id routine: 0  rate: 131.578947
2017/10/27 13:58:14 Id routine: 1  rate: 129.870130
2017/10/27 13:58:14 Current total rate was 261.45 K/s
2017/10/27 13:58:14 Starting 2 threads
2017/10/27 13:58:24 Id routine: 1  rate: 144.927536
2017/10/27 13:58:24 Id routine: 0  rate: 151.515152
2017/10/27 13:58:24 Current total rate was 296.44 K/s

2017/10/27 13:59:15 Starting 3 threads
2017/10/27 13:59:25 Id routine: 2  rate: 94.339623
2017/10/27 13:59:25 Id routine: 0  rate: 92.592593
2017/10/27 13:59:25 Id routine: 1  rate: 90.090090
2017/10/27 13:59:25 Current total rate was 277.02 K/s
2017/10/27 13:59:25 Starting 3 threads
2017/10/27 13:59:35 Id routine: 2  rate: 92.592593
2017/10/27 13:59:35 Id routine: 0  rate: 90.090090
2017/10/27 13:59:35 Id routine: 1  rate: 101.010101
2017/10/27 13:59:35 Current total rate was 283.69 K/s

2017/10/27 14:00:12 Starting 4 threads
2017/10/27 14:00:22 Id routine: 1  rate: 56.818182
2017/10/27 14:00:22 Id routine: 3  rate: 56.818182
2017/10/27 14:00:22 Id routine: 0  rate: 61.349693
2017/10/27 14:00:22 Id routine: 2  rate: 62.500000
2017/10/27 14:00:22 Current total rate was 237.49 K/s
2017/10/27 14:00:22 Starting 4 threads
2017/10/27 14:00:32 Id routine: 1  rate: 67.114094
2017/10/27 14:00:32 Id routine: 3  rate: 61.349693
2017/10/27 14:00:32 Id routine: 0  rate: 57.803468
2017/10/27 14:00:32 Id routine: 2  rate: 65.789474
2017/10/27 14:00:32 Current total rate was 252.06 K/s

And, here is the concurrent code with the goroutines:

package main

import (
    "fmt"
    "log"
    "sync"
    "time"
)

var (
    tryArr           []string
    goroutineQuit    = make(chan struct{})
    concurrencyMapHQ = struct {
        sync.RWMutex
        HQ map[int]float64
    }{HQ: make(map[int]float64)}
)

func rateStats() {
    var totalRate float64
    for i, rate := range concurrencyMapHQ.HQ {
        log.Printf("Id routine: %d  rate: %f", i, rate)
        totalRate += rate
    }

    log.Printf("Current total rate was %.2f K/s", totalRate)
}

func stopThreads(threads int) {
    for i := 0; i < threads; i++ {
        goroutineQuit <- struct{}{}
    }

    rateStats()
}

func runThreads(threads int, steps int) {
    log.Printf("Starting %d threads", threads)

    for i := 0; i < threads; i++ {
        i := i
        go func(id int, steps int) {
            calculate(i, steps)
        }(i, steps)
    }
}

func calculate(idRoutine int, steps int) {
    var (
        possibles []string
        numBatchs = 0
        t1        = time.Now()
    )

    for {
        select {
        case <-goroutineQuit:
            return
        default:
            possibles = nil

            for _, nonce := range tryArr {
                possibles = append(possibles, nonce)
            }

            numBatchs++
            if numBatchs == 99 {
                t2 := time.Now()

                timeExecution := t2.Sub(t1) / time.Millisecond

                concurrencyMapHQ.Lock()
                concurrencyMapHQ.HQ[idRoutine] = float64(steps) / float64(timeExecution)
                concurrencyMapHQ.Unlock()

                numBatchs = 0
                t1 = t2

            }
        }
    }
}

func main() {
    threads := 4
    steps := 10000

    tryArr = make([]string, steps)
    for i := 0; i < steps; i++ {
        tryArr[i] = fmt.Sprintf("indice: %d", i)
    }

    for {
        runThreads(threads, steps)
        time.Sleep(10 * time.Second)
        stopThreads(threads)

        runThreads(threads, steps)
        time.Sleep(10 * time.Second)
        stopThreads(threads)
    }
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • douyinlai2169 2017-10-27 14:55
    已采纳

    Allocate possibles for the default case:

    default:
        //possibles = nil
        possibles = make([]string, 0, len(tryArr))
    

    For example, possibles = nil,

    2017/10/27 10:59:35 GOMAXPROCS: 4
    2017/10/27 10:59:35 Starting 4 threads
    2017/10/27 10:59:45 Id routine: 3  rate: 20.576132
    2017/10/27 10:59:45 Id routine: 2  rate: 21.276596
    2017/10/27 10:59:45 Id routine: 0  rate: 19.960080
    2017/10/27 10:59:45 Id routine: 1  rate: 21.276596
    2017/10/27 10:59:45 Current total rate was 83.09 K/s
    2017/10/27 10:59:45 Starting 4 threads
    2017/10/27 10:59:55 Id routine: 2  rate: 20.533881
    2017/10/27 10:59:55 Id routine: 0  rate: 20.576132
    2017/10/27 10:59:55 Id routine: 1  rate: 19.801980
    2017/10/27 10:59:55 Id routine: 3  rate: 20.746888
    2017/10/27 10:59:55 Current total rate was 81.66 K/s
    57.08user 2.16system 0:20.02elapsed 295%CPU
    

    And, possibles = make([]string, 0, len(tryArr)),

    2017/10/27 10:57:33 GOMAXPROCS: 4
    2017/10/27 10:57:33 Starting 4 threads
    2017/10/27 10:57:43 Id routine: 0  rate: 112.359551
    2017/10/27 10:57:43 Id routine: 1  rate: 104.166667
    2017/10/27 10:57:43 Id routine: 2  rate: 91.743119
    2017/10/27 10:57:43 Id routine: 3  rate: 112.359551
    2017/10/27 10:57:43 Current total rate was 420.63 K/s
    2017/10/27 10:57:43 Starting 4 threads
    2017/10/27 10:57:53 Id routine: 0  rate: 123.456790
    2017/10/27 10:57:53 Id routine: 1  rate: 126.582278
    2017/10/27 10:57:53 Id routine: 2  rate: 113.636364
    2017/10/27 10:57:53 Id routine: 3  rate: 119.047619
    2017/10/27 10:57:53 Current total rate was 482.72 K/s
    58.11user 2.32system 0:20.01elapsed 302%CPU
    

    What are your results?


    With increasing "threads" [1,2,3,4] and possibles = make([]string, 0, len(tryArr)),

    $ cat /proc/cpuinfo | grep 'cpu cores' | uniq
    cpu cores   : 4
    

    .

    2017/10/27 11:19:03 GOMAXPROCS: 4
    2017/10/27 11:19:03 Starting 1 threads
    2017/10/27 11:19:13 Id routine: 0  rate: 285.714286
    2017/10/27 11:19:13 Current total rate was 285.71 K/s
    2017/10/27 11:19:13 Starting 1 threads
    2017/10/27 11:19:23 Id routine: 0  rate: 312.500000
    2017/10/27 11:19:23 Current total rate was 312.50 K/s
    24.66user 1.13system 0:20.01elapsed 128%CPU
    

    .

    2017/10/27 11:19:28 GOMAXPROCS: 4
    2017/10/27 11:19:28 Starting 2 threads
    2017/10/27 11:19:38 Id routine: 0  rate: 238.095238
    2017/10/27 11:19:38 Id routine: 1  rate: 217.391304
    2017/10/27 11:19:38 Current total rate was 455.49 K/s
    2017/10/27 11:19:38 Starting 2 threads
    2017/10/27 11:19:48 Id routine: 1  rate: 192.307692
    2017/10/27 11:19:48 Id routine: 0  rate: 217.391304
    2017/10/27 11:19:48 Current total rate was 409.70 K/s
    46.14user 2.07system 0:20.00elapsed 240%CPU
    

    .

    2017/10/27 11:19:53 GOMAXPROCS: 4
    2017/10/27 11:19:53 Starting 3 threads
    2017/10/27 11:20:03 Id routine: 2  rate: 142.857143
    2017/10/27 11:20:03 Id routine: 1  rate: 149.253731
    2017/10/27 11:20:03 Id routine: 0  rate: 147.058824
    2017/10/27 11:20:03 Current total rate was 439.17 K/s
    2017/10/27 11:20:03 Starting 3 threads
    2017/10/27 11:20:13 Id routine: 2  rate: 153.846154
    2017/10/27 11:20:13 Id routine: 1  rate: 156.250000
    2017/10/27 11:20:13 Id routine: 0  rate: 153.846154
    2017/10/27 11:20:13 Current total rate was 463.94 K/s
    52.41user 2.21system 0:20.01elapsed 273%CPU
    

    .

    2017/10/27 11:20:25 GOMAXPROCS: 4
    2017/10/27 11:20:25 Starting 4 threads
    2017/10/27 11:20:35 Id routine: 1  rate: 106.382979
    2017/10/27 11:20:35 Id routine: 2  rate: 102.040816
    2017/10/27 11:20:35 Id routine: 0  rate: 125.000000
    2017/10/27 11:20:35 Id routine: 3  rate: 117.647059
    2017/10/27 11:20:35 Current total rate was 451.07 K/s
    2017/10/27 11:20:35 Starting 4 threads
    2017/10/27 11:20:45 Id routine: 1  rate: 111.111111
    2017/10/27 11:20:45 Id routine: 2  rate: 112.359551
    2017/10/27 11:20:45 Id routine: 0  rate: 119.047619
    2017/10/27 11:20:45 Id routine: 3  rate: 128.205128
    2017/10/27 11:20:45 Current total rate was 470.72 K/s
    58.80user 2.20system 0:20.01elapsed 304%CPU
    

    In summary, you appear to be benchmarking the Go garbage collector. Garbage collection is not free. Minimize your allocations. Use the Go testing package benchmark facilities.

    点赞 评论

相关推荐 更多相似问题