기본 콘텐츠로 건너뛰기

Android Froyo의 Dalvik VM JIT compile에 대해서

Android Froyo 버전의 Dalvik VM 부터는 JIT 컴파일러를 지원하여 VM의 성능이 약 5배 정도 향상되었다고 한다.
Google IO 2010에서 제공한 JIT 컴파일러 세션을 보고 완전하지는 않지만 부분적으로 이해한 내용을 정리해보고자 한다. 우선, 시간이 허락한다면 아래 세션 비디오를 먼저 살펴보시길.



Dalvik VM의 JIT 컴파일러는 Trace-granuality JIT 방식이다. 무슨 의미인고 하니 실행하는 바이트 코드 중에서 정말 반복이 심한 부분 영역만 골라서 컴파일한다는 것이다.
기존 Java가 제공하는 HotSpot 컴파일러의 경우 Profiling을 통해 빈번히 실행되는 Java Method를 컴파일해서 성능을 개선하지만 Dalvik VM은 Method 단위가 아닌 작은 코드 블럭(주로 반복문이 될 가능성이 높겠다)을 컴파일한다. 나름대로 장단점이 있겠지만 Google이 주장하기로는 모바일 장치에는 이 방식이 더 좋다고 한다. (뭐... 검증해보지 않아서 진실은 모르겠다.)

Google IO 세션에서 설명한 내용을 이용하여 좀 더 자세히 살펴보자.

위 그림에서 Start 지점에서는 컴파일할 대상 코드 블럭을 찾기위해 trace를 시작할 trace head 부분을 지정한다.
trace head로는 backward branch, method entry point, indirect branch와 같은 코드 부분을 이용한다. trace haed를 지정하였으면 이 위치에 대해 profile count를 관리하는데 코드 실행 path가 매번 이 지점을 다시 지나갈 때 profile count값을 증가시키게 된다.

profile count 값이 미리 정의된 threshold를 넘었는지 확인하고 그렇지 않다면 interpretation을 계속하고 만일, threshold를 넘었다면 현재 trace하고 있는 코드 블럭에 대한 translation이 존재하는지 확인한다. 지금은 처음 실행된 경우를 가정하니 당연히 translation이 존재하지 않는다.

UPDATE: profile count를 확인하는 과정은 Dalvik의 Mterp/out 폴더에 있는 InterpAsm ... 으로 시작하는 어셈블러 소스에 작성되어 있다. InterpAsm-armv5te.S 파일을 보면 9782 라인 쯤에 common_updateProfile 코드에서 profiling 과정을 처리한다.
9783     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function

9784     lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits

9785     ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter

9786     GET_INST_OPCODE(ip)

9787     subs    r1,r1,#1           @ decrement counter

9788     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
위와 같이 코드는 매우 간단하며 (당연히 성능을 고려하여 profiling 처리가 전체 성능에 최소한의 영향을 미치도록 작성하였다.) counter의 값을 감소하여 0이 되면 trace selection mode로 진입하게 된다. 참고로 counter의 값은 ARMv5의 경우는 200, ARMv7의 경우는 40으로 설정되어 있다.

이제 Dalvik VM은 trace building mode로 진입하고 interpretation을 진행한다. trace buidling 모드에서는 interpretation된 byte code들을 translation을 위해 계속 저장하다가 특정 사이즈만큼 모이면 compiler thread에서 컴파일하여 translation cache에 저장한다. 다음에 다시 동일 지점의 코드를 실행하면 translation cache에 컴파일되어 있는 코드를 이용하여 성능 향상이 이루어진다.

UPDATE: trace selection이라고 불리는 위 과정을 수행하는 코드는 Dalvik의 Jit.c 파일에 있는 dvmCheckJit 함수에서 이루어진다. interpreter mode가 kJitTSelect 상태이면 compile할 byte code를 선택하는 모드로 동작을 하고 특정 조건을 만족하면 (trace 크기가 어느 정도 이상이 되거나 unconditional한 branch가 발생하거나 ...) kJitTSelectEnd 상태로 interpreter mode를 변경하여 dvmCompilerWorkEnqueue 함수에 의해 compiler thread가 해당 trace를 compile할 수 있게끔 요청한다.

Google은 JIT가 사용하는 메모리의 크기를 약 100KB 정도로 아주 작게 사용한다고 했는데 좀 이상한 점은 translation cache 공간이 꽉차게되면 컴파일된 코드를 싹 지우고 다시 새로 시작한다는 점이다. translation cache 영역에 대해서는 아직 GC로 메모리 관리를 하지 못한다고 한다.

참고자료:

댓글

이 블로그의 인기 게시물

Wireless: HotSpot 2.0 이란?

스마트폰 사용자가 HotSpot 2.0을 지원하는 Wi-Fi 망을 사용하는 경우라면 기존 Wi-Fi 망과 달리 이동통신 망에서 Wi-Fi 망으로의 네트워크 연결 전환이 자연스럽게 이루어진다. 예를 들면, 3G 네트워크를 이용하여 영화를 보고 있다가 HotSpot 2.0 네트워크에 연결이 가능하게 되면 영화 시청 중단 없이 Wi-Fi 망으로 자연스럽게 네트워크 연결이 이동하여 3G 망의 부하도 줄이고 사용자의 네트워크 비용도 절약할 수 있다. 시스코에서 제공한 White Paper 를 참고.

Apple M1 Mac Mini에서 이더리움 (Ethereum) 채굴하기

 돈을 벌 목적은 아니고 이더리움 기술에 대한 호기심에 직접 채굴(마이닝)에 나서 보기로 했다. 머신은 Apple M1 Mac Mini. 스팩을 살펴보니 8 Core GPU에 16GB 메모리를 공유하고 있어 가능은 해보인다. 큰 흐름은 다음과 같다. 채굴한 이더리움을 저장할 지갑을 만든다 만든 지갑의 정보를 잘 보관해둔다 (Secret Recovery Phrase, 지갑의 주소 값) Apple M1용 채굴 프로그램 설치 내 지갑 정보를 이용해서 채굴 프로그램 실행 일단, 채굴한 이더리움을 저장할 지갑(wallet)을 만들어야 한다.  크롬 브라우저 익스텐션 설치로 비교적 간단하게 지갑을 만들 수 있는  https://metamask.io/ 를 이용하기로 했다. 크롬 익스텐션을 설치 후 기존에 만든 지갑이 없으므로 "Create a Wallet"을 선택한다. 패스워드 입력하고 등등의 절차를 거치면 아래와 같은 Secret Recovery Phrase가 나온다. 이 값을 잘 보관해두기 바란다. 나중에 지갑을 복구할 때 필요한 값이다. 이 값이 유출되면 지갑에 모아둔 이더리움을 다 털릴 수 있으므로 안전한 곳에 보관한다. Confirm Your Secret Phrase에서 확인 과정을 거친다. 직접 입력하는 것이 아니라 단어 별 버튼을 일일이 클릭해서 확인해주어야 한다. (좀 번거롭지만 그만큼 Secret Recovery Phrase가 중요함을 인지시키기 위한 과정이다.) 이제 지갑은 준비 완료. 생성된 Account 화면에서 지갑의 주소갑을 얻을 수 있다.  Apple M1용 채굴 프로그램을 설치해보자. Ethminer M1 Github 프로젝트 에서 미리 컴파일된 바이너리를 다운로드 받는다. (Assets를 펼치고 ethminer-m1을 클릭해서 다운 받으면 된다) 원하는 폴더에 파일을 옮겨 놓고 Terminal에서 chmod +x로 실행가능하게 만든다. % mv ~/Downloads/ethminer-m1 .             %   % c

Java: Java for Game? Java가 Game 개발에 어울릴까?

Java가 기업용 서버 소프트웨어 개발에 활발하게 쓰이는 것과 달리 일반 응용프로그램 분야에서는 별로 대접을 받지 못하는 현실을 개선하려면 어떤 분야부터 손보면 좋을까? 로딩타임, 성능, 사용자 인터페이스 등 Java를 이용한 클라이언트 프로그램을 개발하지 않는 이유들은 개발자 별로 서로 다를 것이다. 하지만, 이런 단점에도 불구하고 점점 복잡해지는 소프트웨어를 더 쉽게 다양한 환경에서 동작하도록 만들기 위해서는 Java만큼 이미 성숙한 해결책도 없지 않은가? 클라이언트 개발을 활성화하기 위해 Java를 게임 개발에 활용할 수 있도록 지원하면 어떨까? 역시, 사용자가 직접 쓰는 응용프로그램 중에는 게임이 가장 시장이 큰 분야이니 말이다. 그렇다면, 현재 게임 개발에 Java가 어느 정도 사용되고 있고 미래에 더 활성화 될 가능성은 있을 것인가? 이런 의문점을 가지고 "Java + Game"에 대해 조사해보기로 했다. 1. Java로 개발한 게임들 우선, Java로 개발한 게임들에 대해 살펴보자. Oracle의  Java in Action 웹페이지 를 보면 Java를 이용한 3D MMORPG RuneScape 에 대한 설명이 있다. 가입자가 1억 3000만명이 넘는다고 하다. 실제 게임을 설치해서 실행해보니 WOW같은 화려한 그래픽에는 못미치치만 잘만든 Role Playing 게임이다 Puppy Games 에서 개발한  Revenge of the Titans 게임도 눈여겨 볼 만하다. 이 회사는 작고 손쉽게 즐길 수 있는 게임을 개발하는데 모든 게임을 Java로 만든다. Revenge of the Titans는 Starcraft와 같은 전략 게임으로 너무 머리쓰지 않고 즐길 수 있는 게임이며 그래픽도 신선하다. 개발이 진행 중인 것으로 보이는 Urban Galaxy 라는 게임도 재미있을 것 같다. SF 영화를 보면 자주 등장하는 미래의 빌딩 숲을 날아다니는 자동차로 전투도 치르고 무역도 하며 캐릭터를 키우는 게임으로