과거에는 Foreach를 사용하면 가비지가 생긴다는 이유로 사용을 지양하던 때가 있었다.
구조상 Foreach는 가비지를 발생시키니까 For를 사용해라 라는 식으로만 알고 있었기에
Dictionary같이 Foreach를 써야하는 경우에만 사용했었다.
그래서 이번에는 조금 더 자세히 알아보려고 한다.
우선 사실만 먼저 말하자면 Foreach는 이미 2010년도에 리펙토링되어서 가비지가 쌓이지 않는다.
가비지가 생긴다는 말이 있었던 이유는 유니티 5.4.5버전까지는 꽤 오래된 컴파일러를 사용하고 있었기 때문에
리펙토링된 Foreach가 적용되지 않았던 것이다.
유니티 5.5버전 이후부터는 리펙토링된 Foreach가 적용되었다.
그럼 오래된 컴파일러에서는 왜 가비지가 생겼을까?
그건 내부적으로 박싱이 일어나고 있기 때문이었다.
Generic.List<T>.Enumerator는 struct이고 struct는 ValueType이다.
그리고 Enumerator는 interface들을 상속받고 있는데
interface는 class와 struct 둘 다 사용이 가능하기 때문에 interface에서 정의된 메서드를 호출할 때
ValueType인지 ReferenceType인지 구분하는게 모호하여 모두 ReferenceType으로 처리하고 있다.
이 경우 ValueType인 객체들은 Boxing이 일어나게 되면서 가비지가 쌓이게 되는 것이다.
Array의 경우 컴파일러가 foreach를 for로 변환시켜주고 있기 때문에 가비지가 쌓이지 않지만
List와 Dictionary 같은 애들은 foreach를 그대로 사용하고 있기 때문에 가비지가 발생하게 되는 것이다.
다행히도 앞서 이야기 했듯이 foreach가 리펙토링이 되어서 더 이상 가비지가 쌓이지 않게 되었다.
포인터를 직접 넘겨줌(C/C++의 그 포인터와 거의 동일)으로서
ValueType이든 ReferenceType이든 타입 구분을 신경쓰지 않고 호출할 수 있게 되었다.
이 부분에 대한 이해를 하려면 constrained라는 instruction에 대해 이해가 필요하다고 한다.
(이 부분은 아직 잘 모르는 부분이라 위에 포인터를 직접 넘겨줌으로써 해결되었다 정도만 먼저 알아두자)
인디터에 들어가보면 생각보다 많은 팁, 질문들이 있고 유용한 정보들이 많다.
재미있게 풀어 놓은 팁들도 있으니 꼭 인디게임 개발하는 사람이 아니더라도 이곳에서 유용한 정보를 얻을 수 있다.
'프로그래밍 > 기본기ㆍ자료구조' 카테고리의 다른 글
C# Random - System.Random (0) | 2021.02.16 |
---|---|
메모리 풀과 오브젝트 풀 (0) | 2021.02.11 |
스레드와 프로세스의 차이 (0) | 2021.02.07 |
C# string 비교 == 과 Equals() (2) | 2021.02.05 |
OOP 객체지향 5가지 원칙 (1) | 2021.02.04 |