Unity JIT Spike (JIT 강제로 컴파일 하기) Just In Time




[방법.1]


var preJitCompile =typeof(MyComponent).GetMethod("MethodName");


//preJitCompile != null 체크 생략


preJitCompile.MethodHandle.GetFunctionPointer();




[방법.2]


using System.Reflection;



var method = typeof(A).GetMethod("MethodName", BindingFlags.NonPublic | BindingFlags.Instance);







회사 프로젝트를 최적화 하던 중 몇몇 함수에서 메모리 할당이나 테이블 로드등의 


최초 수행 시 시간이 소모되는 작업이 전혀 없음에도

함수의 최초 1번째 수행시간과 2번째부터의 수행시간이 10:1 이상 차이나는것을 보고 검색과 질문을 해보던 중

JIT Spike라는 개념을 찾았습니다.



- 인터프리터 방식에서 최초 번역시에 만들어진 기계어를 캐싱해 놓는 인터프리터와 컴파일 방식의 혼용입니다.


JIT Spike란 최초번역과 기계어를 캐싱되는 시간에 의한 딜레이 발생을 의미합니다.

해결방법으로는 특정 코드를 미리 캐싱되게 하는 것으로 3가지의 방법이 있는데

1. system.runtime.compilerservices.runtimehelpers.preparemethod("methodname")

 - 이것은 Mono에선 작동하지 않으며 
   (관련 링크- http://www.slideshare.net/flashgamm/unity-internals-memory-and-performance  35, 36페이지)
   Method.MethodHandle.GetFunctionPointer()를 권장하고 있습니다.


2. Method.MethodHandle.GetFunctionPointer()

 - 포럼의 글을 찾다보니 
   효과가 있다고 나왔지만
   에디터&안드로이드 세팅을 한 상태에서 사용 시 수행시간의 변화를 찾지 못했습니다.
   (휴대폰에서 로그를 확인 할 수 있는 플러그인을 사용해 PC에선 변화가 없어도 휴대폰에선 변화가 있는지 보려고 했으나 
    최근에 빌드에 계속 문제가있어서 확인해보지 못했습니다.)

3. fake 로직 수행

 - 최초전투 발생시 렉이 생기는것이 문제였으므로 fake parameter등으로 가짜로 먼저 로직을 수행해놓게 했습니다.


현재 저는 3번방식으로 해결한 상태입니다.

PC에서 확인시에는 그 차이가 10:1임에도 시간 자체가 매우 작지만

휴대폰에서는 수행시간의 차이가 체감되는 수준이었습니다.

안드로이드에서만 적용되며 IOS는 작동방식이 다르므로 신경쓸 필요가 없습니다.

틀린부분도 있을 수 있지만 혹시 도움되는 분들이 있으실 것 같아서 용기내서 올립니다.





---- 이 이하는 2번방법에 관심이 있으신 분들만 보시면 됩니다 ----

현재진행형인 부분으로 저는 typeof(클래스네임).GetMethods() (반환값 MethodInfo[])를 사용해서 

휴대폰에서 작동이 잘 되는지 확인해보려고 하고있습니다.

이때 주의점은 MethodInfo.DeclaredType 이 UnityEngine.Component인 함수를 캐싱하려고하면 유니티가 죽어버리고

또한 오버라이딩 함수의 경우에도 죽게 되 있습니다.

때문에 GetMethods를 사용해서 이름을 얻어와 오버라이딩 함수의 이름을 제거 후 DeclaredType은 if문으로 걸러낸뒤에

적용시키는 코드를 작성해놓았습니다. 빌드문제가 해결되는대로 테스트해볼 예정입니다.


http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_Lecture&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=hit&desc=asc&no=421

반응형

+ Recent posts