Divide and Conquer

Goroutine 스케줄링 본문

성장캐/분산컴퓨팅

Goroutine 스케줄링

10살 2024. 6. 4. 17:04
728x90

https://velog.io/@sunaookamisiroko/Goroutine-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81

고루틴은 (c) N:M 스케줄링을 함

global runqueue에서 M이 G를 하나씩 가져다가 실행
global runqueue는 하나의 자료구조 > M이 동시에 사용하면 race condition 발생 > lock을 사용

그런데, M은 G를 갖기 위해 lock을 기다려야 해서 성능저하로 이어짐
+ 하나의 고루틴의 실행 시간이 길다면 다른 실행되지 않는 고루틴은 기아 상태에 빠질 수 있다

Goroutine locality

func main() {
	var wg sync.WaitGroup
    wg.Add(10)
    for i := 0; i < 10; i++ {
    	go func() {
        	defer wg.Done()
            doSomething()
        }()
    }
    wg.Wait()
}

main G가 새로운 G를 10개 만듦

func sender(ch chan int) {
	for i := 0; i < 10; i++ {
    	ch <- i
    }
    close(ch)
}

func reciever(ch chan int) {
	for {
    	msg, ok := <- ch
        if !ok {
        	break
        }
        process(msg)
    }
}

func process(msg int) {
	fmt.Println("Reciedved:", msg)
}

func main() {
	ch := make(chan int)
    go sender(ch)
    reciever(ch)
}

다음 예시 코드는 100개의 고루틴으로 동시에 열어서 파일을 만들고 쓰는 작업을 한다
https://changhoi.kim/posts/go/go-scheduler/

package main  
  
import (  
   "fmt"  
   "os"   
   "runtime/pprof"   
   "sync"
)  
  
func main() {  
   threadProfile := pprof.Lookup("threadcreate")  
   fmt.Printf("thread count before start: %d\n", threadProfile.Count())  
   var wg sync.WaitGroup  
   wg.Add(100)  
   for i := 0; i < 100; i++ {  
      go func(n int) {  
         defer wg.Done()  
         filename := fmt.Sprintf("files/%d-file", n)  
         f, err := os.Create(filename)  
         if err != nil {  
            panic(err)  
         }  
  
         defer func() {  
            if err := f.Close(); err != nil {  
               fmt.Println(err)  
            }  
  
            err := os.Remove(filename)  
            if err != nil {  
               fmt.Println(err)  
            }  
         }()  
  
         var str []byte  
         for j := 0; j < 1000; j++ {  
            str = append(str, byte(j))  
         }  
         _, err = f.Write(str)  
         if err != nil {  
            panic(err)  
         }  
  
      }(i)  
   }  
  
   wg.Wait()  
   fmt.Printf("threads count aftre program: %d\n", threadProfile.Count())  
}

 

반응형
Comments