Go는 고루틴을 사용하고 자바, C++과 같은 언어는 쓰레드를 사용합니다. 둘 간의 차이점은 무엇일까요? 우리는 3가지 요소를 통해서 확인 할 수 있습니다. 바로 메모리 소비, 설치와 철거 비용, Context Switching 비용입니다.메모리 소비고루틴은 생성하는데에 많은 메모리를 필요로 하지 않습니다. 오직 2kB의 스택 공간만 필요로 합니다. 고루틴을 할당하고 필요에 따라 힙 저장 공간을 확보하여 사용합니다. 반대로 쓰레드는 쓰레드의 메모리와 다른 쓰레드의 메모리 간의 경비 역할을 하는 Guard page라고 불리는 메모리 영역과 함께 1Mb(500배 더 큼)로 시작합니다.따라서 수신 요청을 처리하는 서버는 문제 없이 요청 한 건 당 하나의 고루틴을 만들 수 있지만, 요청 한 건 당 하나의 쓰레드는 결과적으로 OutOfMemoryError가 일어나게 될 것 입니다. 이런 일은 자바에 한정되어 있는 것이 아닙니다. 동시성의 주요 수단으로 OS 쓰레드를 사용하는 언어라면 언젠가는 이 문제에 대면할 것입니다.설치와 철거 비용쓰레드는 거대한 설치와 철거 비용을 가집니다. 왜냐하면 쓰레드는 OS로부터 리소스를 요청해야 하고 작업이 끝나면 리소스를 돌려줘야 하기 때문입니다. 이 문제의 차선책으로는 쓰레드의 Pool을 유지하는 것입니다. 대조적으로, 고루틴은 런타임에서 만들어지고 파괴되는 작업들이 매우 저렴하다. 그렇기 때문에 Go는 고루틴의 메뉴얼 관리를 지원하지 않습니다.Context Switching 비용만약 쓰레드가 Blocking된다면 다른 쓰레드가 그 자리를 스케쥴링해야 합니다. 쓰레드들은 우선적으로 스케쥴링되고, 쓰레드가 바뀔 동안, 스케쥴러는 모든 레지스터들을 save/restore해야 합니다. 즉, 16개의 범용 레지스터, PC(Program Counter), SP(Stack Pointer), segment 레지스터, 16개의 XMM 레지스터, FP coprocessor state, 16개의 AVX 레지스터, 모든 MSR들 등을 save/restore해야 합니다. 이것은 쓰레드들 간의 빠른 전환이 있을 때 매우 중요합니다.고루틴은 협조적으로 스케쥴링되고 교체가 일어날 때, 오직 3개의 레지스터만이 save/restore되기 위해 필요합니다. 바로 Program Counter, Stack Pointer 그리고 DX입니다. 비용은 훨씬 덜 듭니다.일찍이 논의했던 바와 같이, 고루틴의 갯수는 일반적으로 훨씬 많지만, 2가지 이유에 의해 교체 시간에 차이점을 낳지 않습니다. 오직 동작하는 고루틴들만이 고려되고, Blocking된 것들을 고려되지 않습니다. 또한, 현대의 스케쥴러들은 O(1) complexity를 가집니다. 즉 교체 시간이 고루틴의 수에 의해 영향을 받지 않는다는 의미입니다.어떻게 고루틴이 실행되는가일찍이 언급했던 바와 같이, 런타임은 프로그램의 시작부터 끝나는 시점까지 내내 고루틴을 관리합니다. 런타임은 모든 고루틴을 다중화되어 있는 조금의 쓰레드들에 할당됩니다. 어느 시점에서, 각각의 쓰레드는 하나의 고루틴을 실행할 것입니다. 만약 그 고루틴이 Blocking되었다면, 그 쓰레드는 자기 대신에 실행할 다른 고루틴으로 교체할 것입니다.고루틴들이 협조적으로 스케쥴링되기 때문에, 계속해서 고리모양을 만드는(loop하는) 고루틴은 동일한 쓰레드에서 다른 고루틴들을 굶겨 죽일 수 있습니다. Go 1.2에서, 이 문제는 function을 입력할 때 Go 스케쥴러가 가끔 작동함으로써 다소 완화되고, 따라서 non-inlined function 명령을 포함하는 루프를 선점합니다.고루틴 Blocking고루틴은 저렴합니다. 또한 고루틴은네트워크 입력sleeping채널 오퍼레이션sync 패키지 primitive들로 인한 블로킹때문에 블록되었을 때, 자신이 multiplex된 쓰레드를 블록하지 않습니다.수많은 고루틴들이 만들어짐에도 불구하고, 만약 대부분의 고루틴들이 위 목록들 중 하나에 Blocking당한다면 런타임이 대신에 또다른 고루틴을 스케쥴링하기 때문에 이는 시스템 리소스들의 낭비가 아닙니다.간단히 말해서, 고루틴들은 쓰레드보다 가벼운 관념입니다. Go 프로그래머는 쓰레드를 다루지 않고, 유사하게 OS는 고루틴의 존재를 알지 못합니다. OS의 관점에서, Go 프로그램은 이벤트 기반 C 프로그램과 같이 행동할 것입니다.쓰레드와 프로세서비록 당신이 런타임이 만들 쓰레드들의 수를 직접적으로 조정할 수 없더라도, 프로그램에 의해 이용되는 프로세서 코어들의 수를 조정하는 것은 가능합니다. 이것은 runtime.GOMAXPROCS(n)를 호출하는것과 함께 GOMAXPROCS 변수를 설정하는 것으로 이루어집니다. 코어들의 개수를 증가하는 것은 아마 당신의 프로그램의 성능을 증가시키는 것에 필수적이지는 않을 것입니다. 프로파일링 툴들은 당신의 프로그램을 위한 이상적인 코어의 개수들을 찾는 데 사용될 수 있습니다.
https://stonzeteam.github.io/How-Goroutines-Work/

이렇게나 훌륭하다