C#은 stackless한 코루틴을 지원합니다

  • stackless 코루틴은 stackful 코루틴처럼 사기군같은 컨텍스트 스위칭 없이 자체 상태머신을 이용한 멀쩡해보이는 방법으로 구현한다.

Stackful Coroutines vs Stackless Coroutines

Stackful Coroutines

먼저 스택풀 코루틴(Stackful Coroutine)은 함수 호출시에 사용되는 분리된 스택을 가지고 있다. 코루틴이 어떻게 동작하는지 정확하게 이해하기 위해서 로우레벨 관점에서 간단히 함수 프레임과 함수 호출에 대해서 살펴볼 것이다. 하지만 먼저 스택풀 코루틴의 특성에 대해서 알아보자.

  • 스택풀 코루틴은 자신만의 스택을 가지고 있다.
  • 스택풀 코루틴의 수명은 호출한 코드로부터 독립적이다.

스택이란 것은 메모리 관점에서 볼 때 연속된 메모리 블럭이며, 스택은 지역변수 및 함수 인자등을 저장하기 위해 필요하다. 하지만 더 중요한 것은 각 함수 호출 후에 추가적인 정보가 스택에 배치되어 호출된 함수가 피호출자(callee)에게 반환하고 프로세서 레지스터를 복원하는 방법을 알려주게 된다.

몇가지 레지스터들은 특정 목적을 가지고 있으며 함수 호출시 스택에 저장된다. 이러한 레지스터는 다음과 같다.

  • SP – Stack Pointer
  • LR – Link Register
  • PC – Program Counter

스택포인터 (Stack Pointer)는 현재 함수 호출에 속하는 스택의 시작주소를 가지고 있는 레지스터다. 이 값 덕분에 스택에 저장된 인수와 지역 변수를 쉽게 참조할 수 있다.

링크 레지스터(Link Register) 함수 호출에서 매우 중요하다. 현재 함수 실행이 끝난 후 실행할 코드가있는 반환 주소(수신자 주소)를 저장한다. 함수가 호출되면 PC가 LR에 저장되고, 함수가 반환되면 LR을 사용하여 PC가 복원된다.

프로그램 카운터(Program counter)는 현재 실행중인 명령어의 주소다.

함수가 호출 될 때마다 링크 레지스터가 저장되므로 함수가 완료된 후 반환 할 위치를 알 수 있다.

함수의 호출과 반환에서 PC 및 LR 레지스터의 동작

스택풀 코루틴이 실행되면 호출 된 함수는 이전에 할당 된 스택을 사용하여 인수와 지역 변수를 저장한다. 함수 호출은 스택풀 코루틴에 대한 모든 정보를 스택에 저장하기 때문에 코루틴에서 호출되는 모든 함수들의 실행을 중단 할 수 있다.

Stackless Coroutines

스택리스 코루틴(Stackless Coroutine)은 스택풀 코루틴과 비교했을 때 약간의 차이점이 있다. 그러나 주요 특징은 여전히 시작(started)되고, 스스로 중단(suspended) 된 후에 다시 재개(resumed)할 수 있다는 점이다.

스택리스 코루틴의 특징은 다음과 같다.

  • 코루틴은 호출자(caller)와 강하게 연결되어 있다. 코루틴에 대한 호출은 실행을 코루틴으로 전송하고 코루틴에서 양보(yield)하는 것은 호출자에게 돌아온다.
  • 스택풀 코루틴은 스택의 수명만큼 유지 되지만, 스택리스 코루틴은 객체의 수명만큼 유지된다.

그러나 스택리스 코루틴의 경우 전체 스택을 할당할 필요가 없기 때문에 훨씬적은 메모리를 요구하지만, 그 때문에 몇가지 제약사항이 생긴다.

스택이 없다면 메모리에서 스택을 할당하지 못하면 어떻게 동작하는거지? 스택에 저장될 모든 데이터는 어디로 가는걸까?라는 의문이 생길 수 있다.  정답은 바로 호출자의 스택을 사용하는 것이다.

스택리스 코루틴은 최상위 레벨(top-level) 함수에서만 스스로를 중단(suspend) 할수 있다. 일반적인 함수의 경우, 데이터가 호출 수신자 스택에 할당되기 때문에 코루틴에서 호출 된 모든 함수는 코루틴이 중단되기 전에 완료되어야 한다. 코루틴이 상태를 유지하는 데 필요한 모든 데이터는 Heap 메모리에 동적으로 할당된다. 이것은 일반적으로 미리 할당 된 전체 스택보다 크기가 훨씬 작은 두 개의 지역 변수와 인수를 사용한다.

코루틴 중단 및 재개에서 기억해야 할 데이터가 훨씬 적지만 코루틴은 최상위 레벨 함수에서만 일시 중단하고 자신을 반환 할 수 있다. 모든 함수 및 코루틴 호출은 동일한 방식으로 발생하지만 코루틴의 경우 일부 추가 데이터를 호출에서 보존해야 중단 지점으로 이동하고 지역 변수의 상태를 복원하는 방법을 알 수 있다. 게다가 함수 프레임과 코루틴 프레임 사이에는 차이가 없다.

코루틴은 다른 코루틴을 호출 할 수도 있다. 스택리스 코루틴의 경우, 하나에 대한 각 호출이 새로운 코루틴 데이터를 위한 새로운 공간을 할당하게 된다. (코루틴에 대한 여러 호출은 다양한 동적 메모리 할당을 유발할 수 있음).

코루틴을 사용하기 위해서는 코루틴을 지원하는 언어가 필요한 이유는 컴파일러가 코루틴의 상태를 설명하는 변수를 결정하고 중단 지점으로의 점프를 위한 보일러 플레이트 코드를 생성해야 하기 때문이다.

 

 

ref : https://pjc0247.tistory.com/100

ref : https://www.charlezz.com/?p=44635 

반응형

+ Recent posts