- Unity가 사용하는 Mono 런타임은 최신 .NET 대비 현저히 느린 실행 속도를 보이며, 동일한 C# 코드가 최대 15배까지 차이 나는 사례가 있음
- 실제 게임 코드에서 Mono 기반 Unity 실행은 100초, 동일 코드의 .NET 실행은 38초로 측정되어, 디버깅과 테스트 효율에도 큰 영향을 줌
-
Release 모드에서도 Mono는 30초, .NET은 12초로, 최적화된 환경에서도 2.5배 이상 성능 차이가 유지됨
- 원인은 Mono의 비효율적인 JIT 컴파일과 인라이닝 실패, 메모리 복사 과다 등으로, .NET의 최신 CoreCLR JIT 최적화와 대비됨
- Unity가 CoreCLR 기반 .NET 현대화를 완성하면 게임과 에디터 모두에서 큰 성능 향상이 가능하며, 이는 모든 Unity 프로젝트의 숨은 성능세 제거로 이어질 전망
Unity의 Mono 사용 배경
- Unity는 2006년부터 Mono 프레임워크를 사용해 C# 코드를 실행
- 당시 Mono는 유일한 멀티플랫폼 .NET 구현체였으며, 오픈소스로 Unity가 수정 가능
- 2014년 이후 Microsoft가 .NET Core를 오픈소스로 공개하고, 2016년 .NET Core 1.0을 출시
- 이후 Roslyn 컴파일러, 새 JIT, 성능 개선 등 .NET 생태계가 빠르게 발전
- 2018년 Unity 엔지니어들은 CoreCLR 포팅 작업을 진행 중이라 밝히며, Mono 대비 2~10배 성능 향상을 기대
- 그러나 2025년 말 현재까지도 CoreCLR 기반 게임 실행은 불가능한 상태
Mono와 .NET의 성능 격차
- Unity 프로젝트의 시뮬레이션 코드를 Unity 외부에서 .NET으로 실행해 직접 비교
- Unity/Mono 환경: 100초, .NET 환경: 38초 (Debug 모드 기준)
-
Release 모드에서는 Mono 30초, .NET 12초로 차이가 유지
- .NET은 4K×4K 맵을 3초 내 생성하는 등 멀티스레드 최적화가 뛰어남
- Mono의 비효율적 코드 생성이 주요 원인으로, 단순 루프에서도 15배 속도 차이 발생
어셈블리 비교: Mono vs .NET
- 동일한 테스트 코드로 생성된 x64 어셈블리 비교 결과
- .NET JIT은 루프 불변식을 루프 외부로 이동(hoisting) , 최소한의 레지스터 연산만 수행
- Mono는 수십 개의 mov 명령어로 메모리 복사를 반복하며, 비효율적 인라이닝으로 성능 저하
-
int.MaxValue 반복 루프 실행 시간
- .NET: 750ms, Mono: 11,500ms, Unity Editor(Debug): 67,000ms
- Mono는 루프 내에서 불필요한 메모리 이동과 비교 연산을 반복 수행
CoreCLR 도입의 의미
- CoreCLR은 최신 JIT, Span<T> API, SIMD 최적화, 하드웨어 명령어 지원 등 현대적 기능 제공
- 이러한 기능은 추가적인 2배 이상 성능 향상 가능성
- Unity의 Burst 컴파일러는 LLVM 기반으로 네이티브 코드를 생성하지만, C# 기능 제한이 존재
- CoreCLR의 현대적 JIT은 Burst와 유사한 성능을 제공하면서 언어 제약이 적음
- CoreCLR은 AOT(사전 컴파일) 지원으로 시작 속도 개선과 JIT 제한 플랫폼(iOS 등) 대응 가능
- 그러나 Unity는 여전히 IL2CPP 유지 방침을 밝힘
결론: Unity의 .NET 현대화 필요성
- Mono는 최신 .NET 대비 1.5~3배 이상 느린 실행 성능을 보이며, 이는 모든 Unity 프로젝트의 숨은 비용으로 작용
- CoreCLR 도입 시 기대 효과
-
런타임 성능 향상, 빠른 반복 빌드, GC 개선, 도메인 리로드 제거, 관리 코드 비중 확대
- Unity 6.x 로드맵에 .NET Modernization이 포함되어 있으나, 2026년 이후로 예정
- CoreCLR 지원이 완성되면 Unity 개발자와 플레이어 모두에게 실질적 성능 혁신 제공 가능
- 현재로서는 Mono의 한계가 Unity 생태계 전체의 성능 병목으로 남아 있음