SlideShare a Scribd company logo
1 of 46
Nexon Korea
이무림
편리하고 성능좋게 Enum 사용하기
Enum의 Boxing을 어찌할꼬?
발표자소개
⚫ 넥슨 데브캣 스튜디오 MT팀
⚫ <런웨이 스토리>
⚫ <로드러너 1>
⚫ <링토스 세계여행>
⚫ <마비노기 2>
⚫ <마비노기 360>
⚫ <루니아 전기>
이무림
목차
⚫ Enum 과 Boxing
⚫ 정석적 해법
⚫ Generic Enum 과 Int 사이의 변환
▪ 동적 코드 생성
▪ C++ Union 트릭
▪ Unsafe Pointer 트릭
⚫ EnumDictionary
Enum 과 Boxing
Boxing 이란?
⚫ 값 타입을 참조 타입으로 변환
▪ ex) int -> object
⚫ 값 타입은 Stack 메모리에 위치
⚫ 참조 타입은 Heap 메모리에 위치
⚫ Heap 에 공간을 할당해서(Box)
Stack 에 있는 값을 복사해 넣음
Boxing 예제
Boxing의 뒷처리
⚫ 1회성으로 생성된 수많은 Box는
Gabage로 변한다.
⚫ Gabage Collection 이 자주
필요하게 됨
⚫ GC가 발생하면 게임이 멈칫.
Enum과 Generic의 만남
⚫ Enum 타입을 Generic으로 받으면 비교할 때 Boxing을 피할 수가 없다.
Enum과 Generic의 만남
⚫ System.Object.Equals() 메소드가 사용되기 때문
▪ object로 인자를 전달받기 위해 오른쪽 객체가 Boxing된다.
▪ virtual 메소드이므로 왼쪽 인자가 참조객체로 Boxing된다.
Enum과 Generic의 만남
⚫그런 코드 사용 안하면 되지!
⚫그런데 정말 사용하지 않을 수 있을까?
Enum과 Generic의 만남
⚫Dictionary<K, V> 에 Enum Key가 들어간다면?
▪ 설마… MS가 이런 것 하나 알아서 안 해주겠어?
⚫설마설마 하던 그 설마가…… Boxing 발생.
List<T> 너마저도?
⚫ 기본중에서도 기본 컨테이너 List<T>는 Enum 을 잘 다룰 수 있을까?
⚫ Contains(), Remove(), IndexOf()처럼
내부적으로 Equals()를 호출하는 경우 동일하게 Boxing 발생
Enum.HasFlag()
⚫ HasFlag() 메소드는 편리한 Bitmasking 처리를 해준다.
▪ .Net 4.5 에서 사용가능
Enum.HasFlag()
⚫ HasFlag() 함수의 내부를 살펴보자.
⚫ Boxing 이 발생한다.
Box의 크기
⚫ Boxing이 발생하면 메모리를 얼마나 차지할까?
⚫ 값 타입의 최소 크기는 4 byte
⚫ 참조 타입의 최소 크기 12 byte
▪ 32bit System 기준
⚫ Equals() 호출시 Boxing 2번 발생
⚫ 총 24 Byte 사용
⚫ 한 프레임에 40번 비교하면 24 x 40 ~= 1 Kbyte Gabage 발생
정리: Enum과 Boxing
⚫Boxing은 성능에 악영향을 미친다.
최대한 줄여야 한다.
⚫Enum과 Generic이 만나면,
비교과정에서 Boxing이 발생한다.
정석적 해법
정석적 해법
⚫ 표준 컨테이너는 생성자에서 Comparer 를 전달받을 수 있다.
정석적 해법
⚫ Enum 타입 하나당 Comparer 타입 하나를 구현해야 한다.
⚫ 컨테이너를 생성할 때마다 Comparer 를 전달해야 한다.
⚫극한직업: 프로그래머 편
⚫ 이것은 해법인가? 노가다인가?
C# 최신 버전이라면?
⚫ C# 7.3 부터 Generic Contstraint 로 Enum 을 지정가능
⚫ T 가 Enum 인 것을 알고 있으니 Equals()를 최적화 해주겠지?
C# 최신 버전이라면?
⚫ IL 을 확인해보자. (Release 빌드)
▪ box 명령어에서 한번
▪ constrained.callvirt 내부에서 box 발생
정리: 정석적 해법
⚫정석적인 방법은 너무 번거롭고 손이 많이 간다.
⚫최신 스펙의 Enum Generic Constraint 를 이용해도
Boxing이 발생한다.
⚫다른 방법이 없을까?
Generic Enum 과 Int 사이의 변환
Generic Enum 과 Int 사이의 변환
⚫ Enum은 그저 숫자에 불과하다.
▪ BackField 타입을 지정할 수 있다.
▪ 아무것도 없으면 int
⚫ Int 로 변환할 수 있다면 Boxing 없이 비교할 수 있다.
▪ 일반화된 Bitmasking처리도 가능하다.
Generic Enum 과 Int 사이의 변환
⚫ 개별적인 Enum타입은 쉽게 int 로 변환할 수 있다.
⚫ Generic 으로 받은 Enum은 변환이 어렵다.
⚫ 방법을 찾아보자.
동적 코드생성
동적 코드생성
⚫ 개별적인 Enum타입은 쉽게 int 로 변환할 수 있다.
⚫ Generic 으로 받은 Enum은 변환이 어렵다.
⚫ Generic 타입의 구체타입이 무엇이 될것인지
컴파일 시점에서는 확정할 수 없기 때문.
⚫ 프로그램이 실행되는 중에는 구체적인 타입이 무엇인지 알고 있다.
⚫ 즉시 코드를 생성해서 변환한다.
동적 코드생성
⚫ 런타임에 개별 enum 타입을 캐스팅하는 코드를 생성한다.
* ValueCastTo<TTo> 클래스로 분리하지 않으면 유니티 구버전에서는 컴파일 에러가 발생한다.
동적 코드생성
⚫ 사용법
⚫ 동적 코드 생성이라니, 기술 그 자체로 멋있다!
⚫ 문제 해결!
⚫ 하지만 AOT(Ahead Of Time) 플랫폼에서 동작하지 않는다.
▪ 망해라 애플
C++ Union 트릭
C++ Union 트릭
⚫ C#의 조상언어인 C++에는 Union 타입이 존재한다.
⚫ Union에 선언된 필드는 같은 메모리를 액세스한다.
⚫ C#은 Union 타입을 지원하지 않지만
[StructLayout], [FieldOffset] 특성을 사용하여 흉내낼 수 있다.
C++ Union 트릭
⚫ C++ Union 스타일로 필드를 겹치게 배치해서 읽고 쓴다.
C++ Union 트릭
⚫ 잘 동작한다!
⚫ 성능도 너무 좋다!
⚫ 그런데 강타입 언어가 이렇게 쉽게 타입체크를 우회해도 되나?
C++ Union 트릭
⚫ 런타임 구현에 따라 다르다.
⚫ .Net 3.5 Equivalent 에서는 잘 동작
▪ 내부적으로 Mono 2.6.5 런타임 사용
⚫ .Net 4.x Equivalent에서는 부작용 존재
▪ 내부적으로 Mono 4.2.2 런타임 사용
⚫ 이 기법을 적용한 Assembly에 Reflection을 시도하면 예외가 발생한다.
▪ System.TypeLoadException: Generic class cannot have explicit layout.
Unsafe Pointer 트릭
Unsafe Pointer 트릭
⚫ C#에서도 C++처럼 포인터를 사용할 수 있다.
⚫ 단, unsafe 블록 안에서만 가능.
⚫ int 형 포인터를 이용해서 Enum 위치를 읽어들이자.
Unsafe Pointer 트릭
⚫ 포인터를 이용해서 Enum 필드에 접근한다.
Unsafe Pointer 트릭
⚫ 잘 동작한다.
⚫ 컴파일시 -unsafe 스위치가 있어야 컴파일이 가능하다.
⚫ Unity2017.x 에서는 unsafe 가 디폴트
⚫ Unity2018.x 에서는 설정에서 선택가능
* 유니티 구버전에서 unsafe 플래그를 지정하려면 Assets 폴더에 mcs.rsp, csc.rsp 파일을 생성하고 내용에 -unsafe 를 추가한다.
EnumDictionary
EnumDictionary
⚫ Enum을 Key로 사용해도 Boxing이 발생하지 않는 Dictionary
⚫ Enum을 내부에서 int 로 변환해서 저장하고
내보낼 때 다시 Enum타입으로 변환한다.
EnumDictionary
⚫ 구현
EnumDictionary
⚫ #if 를 사용해서 플랫폼에 따라 구현을 선택한다.
⚫ 기본적으로 동적 코드생성을 사용
⚫ Unity 환경에서는
⚫ .Net 3.5 에서는 C++ Union 트릭사용
⚫ .Net 4.x 에서는 Unsafe Pointer 트릭사용
▪ 2018.x 버전에서는 allow unsafe code 옵션을 켜고 쓴다.
EnumDictionary
⚫ 사용법
⚫ 너무너무 편리하다.
EnumDictionary
⚫ 전체 코드
▪ https://github.com/netics01/EnumDictionary
⚫ BitConvert
▪ 모든 Enum 과 Int 변환방식 구현
⚫ EnumDictionary
⚫ EnumHashSet
⚫ 데브캣에서 사용하는 SUF의 일부
▪ Silvervine Unity Framework
* 64bit BackField 를 사용하는 Enum 에는 사용할 수 없다.
감사합니다.
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019

More Related Content

What's hot

[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버Heungsub Lee
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략YEONG-CHEON YOU
 
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012devCAT Studio, NEXON
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직Hoyoung Choi
 
나만의 엔진 개발하기
나만의 엔진 개발하기나만의 엔진 개발하기
나만의 엔진 개발하기YEONG-CHEON YOU
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
 
[NDC 2009] 행동 트리로 구현하는 인공지능
[NDC 2009] 행동 트리로 구현하는 인공지능[NDC 2009] 행동 트리로 구현하는 인공지능
[NDC 2009] 행동 트리로 구현하는 인공지능Yongha Kim
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조Hyunjik Bae
 
[Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용
[Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용 [Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용
[Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용 MinGeun Park
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPSeungmo Koo
 
IndirectDraw with unity
IndirectDraw with unityIndirectDraw with unity
IndirectDraw with unityJung Suk Ko
 
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)Heungsub Lee
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019devCAT Studio, NEXON
 
리플렉션과 가비지 컬렉션
리플렉션과 가비지 컬렉션리플렉션과 가비지 컬렉션
리플렉션과 가비지 컬렉션QooJuice
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기Seungjae Lee
 
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019devCAT Studio, NEXON
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현Bongseok Cho
 
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013devCAT Studio, NEXON
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019devCAT Studio, NEXON
 

What's hot (20)

[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략
 
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직
 
나만의 엔진 개발하기
나만의 엔진 개발하기나만의 엔진 개발하기
나만의 엔진 개발하기
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
 
[NDC 2009] 행동 트리로 구현하는 인공지능
[NDC 2009] 행동 트리로 구현하는 인공지능[NDC 2009] 행동 트리로 구현하는 인공지능
[NDC 2009] 행동 트리로 구현하는 인공지능
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조
 
[Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용
[Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용 [Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용
[Unite17] 유니티에서차세대프로그래밍을 UniRx 소개 및 활용
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCP
 
IndirectDraw with unity
IndirectDraw with unityIndirectDraw with unity
IndirectDraw with unity
 
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
 
리플렉션과 가비지 컬렉션
리플렉션과 가비지 컬렉션리플렉션과 가비지 컬렉션
리플렉션과 가비지 컬렉션
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기
 
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현
 
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
 

More from devCAT Studio, NEXON

김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019devCAT Studio, NEXON
 
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019devCAT Studio, NEXON
 
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019devCAT Studio, NEXON
 
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019devCAT Studio, NEXON
 
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019devCAT Studio, NEXON
 
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019devCAT Studio, NEXON
 
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019devCAT Studio, NEXON
 
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018devCAT Studio, NEXON
 
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018devCAT Studio, NEXON
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018devCAT Studio, NEXON
 
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018devCAT Studio, NEXON
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018devCAT Studio, NEXON
 
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018devCAT Studio, NEXON
 
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018devCAT Studio, NEXON
 
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012devCAT Studio, NEXON
 
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011devCAT Studio, NEXON
 
백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010devCAT Studio, NEXON
 
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017devCAT Studio, NEXON
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017devCAT Studio, NEXON
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017devCAT Studio, NEXON
 

More from devCAT Studio, NEXON (20)

김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
 
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
 
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
 
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
 
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
 
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
 
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
 
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
 
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
 
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
 
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
 
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
 
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
 
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
 
백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010
 
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
 

이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019

  • 1. Nexon Korea 이무림 편리하고 성능좋게 Enum 사용하기 Enum의 Boxing을 어찌할꼬?
  • 2. 발표자소개 ⚫ 넥슨 데브캣 스튜디오 MT팀 ⚫ <런웨이 스토리> ⚫ <로드러너 1> ⚫ <링토스 세계여행> ⚫ <마비노기 2> ⚫ <마비노기 360> ⚫ <루니아 전기> 이무림
  • 3. 목차 ⚫ Enum 과 Boxing ⚫ 정석적 해법 ⚫ Generic Enum 과 Int 사이의 변환 ▪ 동적 코드 생성 ▪ C++ Union 트릭 ▪ Unsafe Pointer 트릭 ⚫ EnumDictionary
  • 5. Boxing 이란? ⚫ 값 타입을 참조 타입으로 변환 ▪ ex) int -> object ⚫ 값 타입은 Stack 메모리에 위치 ⚫ 참조 타입은 Heap 메모리에 위치 ⚫ Heap 에 공간을 할당해서(Box) Stack 에 있는 값을 복사해 넣음
  • 7. Boxing의 뒷처리 ⚫ 1회성으로 생성된 수많은 Box는 Gabage로 변한다. ⚫ Gabage Collection 이 자주 필요하게 됨 ⚫ GC가 발생하면 게임이 멈칫.
  • 8. Enum과 Generic의 만남 ⚫ Enum 타입을 Generic으로 받으면 비교할 때 Boxing을 피할 수가 없다.
  • 9. Enum과 Generic의 만남 ⚫ System.Object.Equals() 메소드가 사용되기 때문 ▪ object로 인자를 전달받기 위해 오른쪽 객체가 Boxing된다. ▪ virtual 메소드이므로 왼쪽 인자가 참조객체로 Boxing된다.
  • 10. Enum과 Generic의 만남 ⚫그런 코드 사용 안하면 되지! ⚫그런데 정말 사용하지 않을 수 있을까?
  • 11. Enum과 Generic의 만남 ⚫Dictionary<K, V> 에 Enum Key가 들어간다면? ▪ 설마… MS가 이런 것 하나 알아서 안 해주겠어? ⚫설마설마 하던 그 설마가…… Boxing 발생.
  • 12. List<T> 너마저도? ⚫ 기본중에서도 기본 컨테이너 List<T>는 Enum 을 잘 다룰 수 있을까? ⚫ Contains(), Remove(), IndexOf()처럼 내부적으로 Equals()를 호출하는 경우 동일하게 Boxing 발생
  • 13. Enum.HasFlag() ⚫ HasFlag() 메소드는 편리한 Bitmasking 처리를 해준다. ▪ .Net 4.5 에서 사용가능
  • 14. Enum.HasFlag() ⚫ HasFlag() 함수의 내부를 살펴보자. ⚫ Boxing 이 발생한다.
  • 15. Box의 크기 ⚫ Boxing이 발생하면 메모리를 얼마나 차지할까? ⚫ 값 타입의 최소 크기는 4 byte ⚫ 참조 타입의 최소 크기 12 byte ▪ 32bit System 기준 ⚫ Equals() 호출시 Boxing 2번 발생 ⚫ 총 24 Byte 사용 ⚫ 한 프레임에 40번 비교하면 24 x 40 ~= 1 Kbyte Gabage 발생
  • 16. 정리: Enum과 Boxing ⚫Boxing은 성능에 악영향을 미친다. 최대한 줄여야 한다. ⚫Enum과 Generic이 만나면, 비교과정에서 Boxing이 발생한다.
  • 18. 정석적 해법 ⚫ 표준 컨테이너는 생성자에서 Comparer 를 전달받을 수 있다.
  • 19. 정석적 해법 ⚫ Enum 타입 하나당 Comparer 타입 하나를 구현해야 한다. ⚫ 컨테이너를 생성할 때마다 Comparer 를 전달해야 한다. ⚫극한직업: 프로그래머 편 ⚫ 이것은 해법인가? 노가다인가?
  • 20. C# 최신 버전이라면? ⚫ C# 7.3 부터 Generic Contstraint 로 Enum 을 지정가능 ⚫ T 가 Enum 인 것을 알고 있으니 Equals()를 최적화 해주겠지?
  • 21. C# 최신 버전이라면? ⚫ IL 을 확인해보자. (Release 빌드) ▪ box 명령어에서 한번 ▪ constrained.callvirt 내부에서 box 발생
  • 22. 정리: 정석적 해법 ⚫정석적인 방법은 너무 번거롭고 손이 많이 간다. ⚫최신 스펙의 Enum Generic Constraint 를 이용해도 Boxing이 발생한다. ⚫다른 방법이 없을까?
  • 23. Generic Enum 과 Int 사이의 변환
  • 24. Generic Enum 과 Int 사이의 변환 ⚫ Enum은 그저 숫자에 불과하다. ▪ BackField 타입을 지정할 수 있다. ▪ 아무것도 없으면 int ⚫ Int 로 변환할 수 있다면 Boxing 없이 비교할 수 있다. ▪ 일반화된 Bitmasking처리도 가능하다.
  • 25. Generic Enum 과 Int 사이의 변환 ⚫ 개별적인 Enum타입은 쉽게 int 로 변환할 수 있다. ⚫ Generic 으로 받은 Enum은 변환이 어렵다. ⚫ 방법을 찾아보자.
  • 27. 동적 코드생성 ⚫ 개별적인 Enum타입은 쉽게 int 로 변환할 수 있다. ⚫ Generic 으로 받은 Enum은 변환이 어렵다. ⚫ Generic 타입의 구체타입이 무엇이 될것인지 컴파일 시점에서는 확정할 수 없기 때문. ⚫ 프로그램이 실행되는 중에는 구체적인 타입이 무엇인지 알고 있다. ⚫ 즉시 코드를 생성해서 변환한다.
  • 28. 동적 코드생성 ⚫ 런타임에 개별 enum 타입을 캐스팅하는 코드를 생성한다. * ValueCastTo<TTo> 클래스로 분리하지 않으면 유니티 구버전에서는 컴파일 에러가 발생한다.
  • 29. 동적 코드생성 ⚫ 사용법 ⚫ 동적 코드 생성이라니, 기술 그 자체로 멋있다! ⚫ 문제 해결! ⚫ 하지만 AOT(Ahead Of Time) 플랫폼에서 동작하지 않는다. ▪ 망해라 애플
  • 31. C++ Union 트릭 ⚫ C#의 조상언어인 C++에는 Union 타입이 존재한다. ⚫ Union에 선언된 필드는 같은 메모리를 액세스한다. ⚫ C#은 Union 타입을 지원하지 않지만 [StructLayout], [FieldOffset] 특성을 사용하여 흉내낼 수 있다.
  • 32. C++ Union 트릭 ⚫ C++ Union 스타일로 필드를 겹치게 배치해서 읽고 쓴다.
  • 33. C++ Union 트릭 ⚫ 잘 동작한다! ⚫ 성능도 너무 좋다! ⚫ 그런데 강타입 언어가 이렇게 쉽게 타입체크를 우회해도 되나?
  • 34. C++ Union 트릭 ⚫ 런타임 구현에 따라 다르다. ⚫ .Net 3.5 Equivalent 에서는 잘 동작 ▪ 내부적으로 Mono 2.6.5 런타임 사용 ⚫ .Net 4.x Equivalent에서는 부작용 존재 ▪ 내부적으로 Mono 4.2.2 런타임 사용 ⚫ 이 기법을 적용한 Assembly에 Reflection을 시도하면 예외가 발생한다. ▪ System.TypeLoadException: Generic class cannot have explicit layout.
  • 36. Unsafe Pointer 트릭 ⚫ C#에서도 C++처럼 포인터를 사용할 수 있다. ⚫ 단, unsafe 블록 안에서만 가능. ⚫ int 형 포인터를 이용해서 Enum 위치를 읽어들이자.
  • 37. Unsafe Pointer 트릭 ⚫ 포인터를 이용해서 Enum 필드에 접근한다.
  • 38. Unsafe Pointer 트릭 ⚫ 잘 동작한다. ⚫ 컴파일시 -unsafe 스위치가 있어야 컴파일이 가능하다. ⚫ Unity2017.x 에서는 unsafe 가 디폴트 ⚫ Unity2018.x 에서는 설정에서 선택가능 * 유니티 구버전에서 unsafe 플래그를 지정하려면 Assets 폴더에 mcs.rsp, csc.rsp 파일을 생성하고 내용에 -unsafe 를 추가한다.
  • 40. EnumDictionary ⚫ Enum을 Key로 사용해도 Boxing이 발생하지 않는 Dictionary ⚫ Enum을 내부에서 int 로 변환해서 저장하고 내보낼 때 다시 Enum타입으로 변환한다.
  • 42. EnumDictionary ⚫ #if 를 사용해서 플랫폼에 따라 구현을 선택한다. ⚫ 기본적으로 동적 코드생성을 사용 ⚫ Unity 환경에서는 ⚫ .Net 3.5 에서는 C++ Union 트릭사용 ⚫ .Net 4.x 에서는 Unsafe Pointer 트릭사용 ▪ 2018.x 버전에서는 allow unsafe code 옵션을 켜고 쓴다.
  • 44. EnumDictionary ⚫ 전체 코드 ▪ https://github.com/netics01/EnumDictionary ⚫ BitConvert ▪ 모든 Enum 과 Int 변환방식 구현 ⚫ EnumDictionary ⚫ EnumHashSet ⚫ 데브캣에서 사용하는 SUF의 일부 ▪ Silvervine Unity Framework * 64bit BackField 를 사용하는 Enum 에는 사용할 수 없다.