개요
- 고루틴을 통해 동시성 처리시 항상 성능이 좋은지 확인
코드
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)
}
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
}
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 키워드에서 즉시 시작하는게 아닌, 스케줄링 되는 방식이 원인으로 추정
- 작업이 비교적 복잡한 경우(=시간이 걸리는 경우), 성능 측면에서 좋음
- 고루틴으로 동시성 처리시, 메모리 측면에서는 나쁨
참고문헌