go에서 가장 많이 들리는 특징이 동시성 처리인 goroutine입니다. 실제로 어떻게 하는 건지 간단하게 구현해보고, 실행 시간 비교를 했습니다.
1. 동시에 처리할 기능.
원칙대로라면 실행시간이 오래 걸리는 기능을 사용해야 하지만, 구현상의 복잡함을 생략하기 위해, 간단한 산술 연산으로 대체하고 실행시간은 sleep을 줘서 처리시간이 오래 걸림을 가정했습니다.
func add100(arg int) (result int){
result = arg + 100
time.Sleep(time.Duration(1000)*time.Microsecond)
return
}
func add1(arg int) (result int) {
result = arg + 1
time.Sleep(time.Duration(10)*time.Microsecond)
return
}
func add10(arg int) ( result int) {
result = arg + 10
time.Sleep(time.Duration(100)*time.Microsecond)
return
}
각각 100, 1, 10을 더하는 코드이며, sleep time을 각각 100ms, 1ms, 10ms를 주었습니다. 순차적으로 실행하게 된다면 실행시간은 111ms 이상 걸리게 될 것입니다.
2. 비교 코드.
순차적으로 실행하는 코드와 goroutine을 이용하여 동시에 처리하는 코드를 만들었습니다. 둘다, 1, 10, 100을 더하는 코드를 순서대로 호출하고 결과를 리턴합니다.
func dowork(arg int)(result1, result2, result3 int) {
result1 = add1(arg)
result2 = add10(arg)
result3 = add100(arg)
return
}
func doworkGoroutine(arg int)(result1, result2, result3 int) {
c1 := make(chan int)
c2 := make(chan int)
c3 := make(chan int)
go func(){ c1 <- add1(arg)} ()
go func(){ c2 <- add10(arg)} ()
go func(){ c3 <- add100(arg)} ()
result1 = <-c1
result2 = <-c2
result3 = <-c3
return
}
3. 실행시간 측정.
순차적으로 실행하는 함수를 먼저 실행하고 시간을 기록한 다음. 동시에 실행하는 함수를 실행하여 시간을 기록 한 후 비교하였습니다.
func main() {
startTime := time.Now()
log.Println( dowork(100))
elapsedTime := time.Since(startTime)
fmt.Printf("duration time1: %s\n", elapsedTime)
startTime2 := time.Now()
log.Println( doworkGoroutine(100))
elapsedTime2 := time.Since(startTime2)
fmt.Printf("duration time2: %s\n", elapsedTime2)
fmt.Printf("duration time: %s vs %s", elapsedTime, elapsedTime2)
}
4. 실행 결과
순차로 실행한 함수는 대체로 130ms 전후로 실행시간이 걸렸으며, 동시에 실행하는 함수는 105ms 전후로 실행시간이 측정되었습니다.
예상대로 순차적으로 실행할 때는 111ms 이상의 시간이 소요되었고, 동시에 실행할 때는 100ms 이상의 시간이 걸리는 것을 확인했습니다. 그리고 goroutine으로 동시성 예제를 구현하는 것이 정말 간단했습니다. java로 구현하려면, 지금 만든 코드의 두배는 더 만들어야 할 것 같은데 말이죠.
반응형