[Go] 고루틴 동시성 성능

natae·2022년 8월 28일
0

Golang

목록 보기
8/11

개요

  • 고루틴을 통해 동시성 처리시 항상 성능이 좋은지 확인

코드

goroutine.go

package study

import (
	"sync"
	"time"
)

func SumNormal(n int, sleepMili int) int {
	result := 0
	for i := 1; i <= n; i++ {
		result += i
		time.Sleep(time.Duration(sleepMili) * time.Millisecond)
	}

	//fmt.Println(result)
	return result
}

func SumGoroutine(n int, sleepMili int) int {
	result := 0
	mutex := sync.RWMutex{}
	endChan := make(chan struct{})

	for i := 1; i <= n; i++ {
		go func(val int) {
			mutex.Lock()
			result += val
			mutex.Unlock()
			time.Sleep(time.Duration(sleepMili) * time.Millisecond)
			endChan <- struct{}{}
		}(i)
	}

	for i := 1; i <= n; i++ {
		<-endChan
	}

	//fmt.Println(result)
	return result
}

goroutine_test.go

package study

import "testing"

func BenchmarkSumNormal(b *testing.B) {
	for i := 0; i < b.N; i++ {
		SumNormal(100, 0)
	}
}

func BenchmarkSumGoroutine(b *testing.B) {
	for i := 0; i < b.N; i++ {
		SumGoroutine(100, 0)
	}
}

func BenchmarkSumNormalSleep(b *testing.B) {
	for i := 0; i < b.N; i++ {
		SumNormal(100, 1)
	}
}

func BenchmarkSumGoroutineSleep(b *testing.B) {
	for i := 0; i < b.N; i++ {
		SumGoroutine(100, 1)
	}
}

출력

$ go test -bench . -benchmem
goos: darwin
goarch: arm64
pkg: codeTest/study
BenchmarkSumNormal-8           	 5002885	       210.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkSumGoroutine-8        	   34526	     34597 ns/op	    7358 B/op	     203 allocs/op
BenchmarkSumNormalSleep-8      	       9	 114462491 ns/op	       8 B/op	       0 allocs/op
BenchmarkSumGoroutineSleep-8   	     956	   1275970 ns/op	   15378 B/op	     303 allocs/op

결론

  • 작업이 간단한 경우, 고루틴으로 동시성 처리를 하면 성능이 오히려 떨어짐
    • 고루틴이 go 키워드에서 즉시 시작하는게 아닌, 스케줄링 되는 방식이 원인으로 추정
  • 작업이 비교적 복잡한 경우(=시간이 걸리는 경우), 성능 측면에서 좋음
    • 위의 코드는 1밀리초를 강제로 추가함
  • 고루틴으로 동시성 처리시, 메모리 측면에서는 나쁨

참고문헌

profile
서버 프로그래머

0개의 댓글