Version: 2017.1
메모리
에셋 검사

코루틴

코루틴은 다른 스크립트 코드와 다르게 실행됩니다. 대부분의 스크립트 코드는 단일 위치의 성능 트레이스 내, 특정 Unity 콜백 호출 아래에 나타납니다. 반면, 코루틴의 CPU 코드는 항상 트레이스의 두 곳에서 나타납니다.

코루틴의 모든 시작 코드(코루틴 메서드의 시작부터 첫 번째 yield가 나타나는 곳까지의 코드)는 트레이스에서 나타나고, 트레이스에서 코루틴이 시작됩니다. 보통 StartCoroutine 메서드가 호출되는 곳에서 나타납니다. Unity 콜백(IEnumerator를 반환하는 Start 콜백 등)에서 생성된 코루틴은 각각의 Unity 콜백에서 최초로 나타납니다.

코루틴의 나머지 모든 코드, 즉 다시 재개되는 시점에서 실행이 종료될 때까지는 Unity 메인 루프에 있는 DelayedCallManager 라인에서 나타나게 됩니다.

왜 이러한 현상이 일어나는지 이해하려면, 코루틴이 실제로 어떻게 실행되는지 알아보아야 합니다.

코루틴은 C# 컴파일러가 자동으로 생성한 클래스의 인스턴스에 의해 작동합니다. 이 오브젝트는 프로그래머에게 하나로 간주되는 메서드를 여러 번 호출하는 코루틴의 상태를 추적하는 데 필요합니다. 코루틴의 로컬 범위 변수는 yield 호출이 진행되는 동안 유지되어야 하기 때문에, 변수는 생성된 클래스에 위치하게 되며, 코루틴이 작동되는 동안 힙에 할당된 상태로 남아 있습니다. 오브젝트는 코루틴의 내부 상태 역시 트래킹하며, yield 호출 이후 코루틴의 어떤 시점에서 재개할 것인지 기억합니다.

이 때문에 코루틴을 시작할 때 발생하는 메모리 사용량은 고정된 오버헤드 비용에 로컬 범위 변수의 크기를 합한 용량과 동일합니다.

코루틴을 시작하는 코드는 이 오브젝트를 생성하고 호출하며, 그 이후 Unity의 DelayedCallManager 가 코루틴의 yield 조건이 만족될 때마다 다시 오브젝트를 호출합니다. 코루틴은 보통 다른 코루틴의 외부에서 시작하기 때문에 코루틴의 실행 비용을 위에 언급된 두 위치로 나누게 됩니다.

위의 스크린샷에서 DelayedCallManager가 다수의 다른 코루틴을 재개하고 있는 것을 볼 수 있습니다. PopulateCharacters, AsyncLoad, LoadDatabase 등이 주목할 만한 것들입니다.

가능한 경우 일련의 작업을 최대한 적은 수의 개별 코루틴으로 압축하는 것이 좋습니다. 코루틴을 중첩하면 코드 명료성을 높이고 유지관리가 용이하지만, 코루틴 추적(tracking) 오브젝트로 인해 더 많은 메모리가 소모됩니다.

만일 코루틴이 매 프레임마다 실행되고, 오래 실행되는 작업에서 yield 호출하지 않는다면, 일반적으로 코루틴을 Update 또는 LateUpdate 콜백으로 교체하는 것이 좋습니다. 특히 오래 실행되거나, 무한 루프되는 코루틴의 경우, 교체하는 것이 좋습니다.

코루틴은 스레드가 아니라는 것을 기억하십시오. 코루틴의 동기 작업은 여전히 메인 스레드에서 실행됩니다. 목표가 메인 스레드에서 소비되는 CPU 시간을 줄이는 것이면 다른 스크립트 코드에서와 마찬가지로 코루틴의 작업 차단을 피하는 것이 중요합니다.

코루틴은 HTTP 전송, 에셋 로드, 파일 I/O 완료 등을 기다리는 것과 같이 긴 시간을 필요로 하는 비동기 작업에 사용하는 것이 가장 유용합니다.

메모리
에셋 검사