2011-02-06 4 views
67

저는 고성능 Android 애플리케이션 (게임)을 제작하고 있습니다. 우선 가독성을 위해 코드를 작성하려고 노력하지만 후드에서 일어나는 일을 내 마음 속에 간직하고 있습니다. C++에서는 컴파일러가 나를 위해 무엇을 할 것인지,하지 않을 것인지에 대해 상당히 좋은 직관을 개발했습니다. Java/Android에서도 동일한 작업을 수행하려고합니다.Dalvik 및 Android 툴체인에서 어떤 최적화가 이루어질 수 있습니까?

따라서이 질문은 웹에서이 주제에 관해서는 거의 알 수 없습니다. Java 컴파일러 Dalvik 변환기 (dx) 및/또는 JITter (Android 2.2 이상)는 다음과 같은 최적화를 수행합니까?

  • 메소드 인라이닝. 어떤 조건에서? private 메서드는 항상 안전하게 인라인 될 수 있습니다. 이 일을 끝내겠습니까? 방법에 대해 public final 방법은 어떨까요? 다른 클래스의 객체에 대한 메소드? static 방법? 컴파일러가 객체의 런타임 유형을 쉽게 추론 할 수 있다면 어떨까요? 가능하다면 메소드를 final 또는 static으로 선언해야합니까?

  • 일반 하위 표현식 제거. 예를 들어 someObject.someField에 두 번 액세스하면 조회가 한 번만 수행됩니까? 게터를 부르면 어떡하지? 어떤 산술 표현식을 두 번 사용하면 어떨까요? 한 번만 평가 되나요? 어떤 식의 결과를 사용하면, 값이 변경되지 않는다고 알고 있는데, 이는 for 루프의 상한입니까?

  • 범위 조회에서 경계를 확인합니다. 툴체인은 특정 조건에서 루프를 제거합니까 (예 : for 원형)?

  • 값 인라이닝. public static final int에 대한 액세스는 항상 인라인됩니까? 그들이 다른 학급에 있더라도? 그들이 다른 패키지에 있어도?

  • 분기 예측. 이것도 얼마나 큰 이슈입니까? 일반적인 Android 기기에서 분기 성능이 큰가요?

  • 간단한 산술. 으로 대체 되나요?

이렇게요 ...

+5

유용 할 수 있습니다. http://developer.android.com/guide/practices/design/performance.html – pablochan

+2

다음은 유용 할 수도 있습니다. http://www.netmite.com/android/mydroid/dalvik/ docs/dexopt.html, http://www.taranfx.com/android-internals-jit-froyo 및 프리젠 테이션의 pdf 버전 : http://www.android-app-developer.co.uk/android- app-development-docs/android-jit-compiler-androids-dalvik-vm.pdf – Lior

+0

@pablochan : 잠시 동안 베개 밑에 있었지만 감사합니다 :) @Lior : 좋은 참조, 저에게 새로운 것입니다. 감사합니다. ! – Thomas

답변

102

이것은 JIT @ Google에서 일하는 엔지니어 중 한 사람인 Ben입니다. Bill과 내가이 프로젝트를 시작했을 때 목표는 가능한 한 빨리 리소스 경쟁 (예 : 메모리 풋 프린트, 컴파일러 스레드에 의해 CPU가 하이재킹 됨)에 미치는 영향을 최소화하면서 가능한 한 빨리 JIT를 전달하여 로우 엔드 장치에서 실행할 수 있도록하는 것이 었습니다. 잘. 따라서 우리는 매우 원시적 인 추적 기반 모델을 사용했습니다. 즉, JIT 컴파일러에 전달 된 컴파일 엔티티는 기본 블록이며 때로는 단일 명령어만큼 짧습니다. 이러한 추적은 인터프리터 및 코드 캐시 조회가 자주 호출되지 않도록 체인이라는 기술을 통해 런타임에 함께 스티칭됩니다. 속도 향상의 주요 원인은 빈번하게 실행되는 코드 경로에 대한 반복적 인 인터프리터 파싱 오버 헤드를 제거하는 데있다.

  • 레지스터 할당
  • 합니다 (JIT는 V7에 대한 Thumb 코드/16 레지스터 생산 이후 v5te 대상에 대한 8 개 레지스터) :

    우리가 프로 요의 JIT로 구현 꽤 많은 지역의 최적화를해야합니까, 말했다 스케줄링 (Dalvik 레지스터를위한 중복 ld/st 제거,로드 호이 스팅, 저장소 싱킹)
  • 중복 중복 검사 (기본 블록에서 이러한 중복성을 찾을 수있는 경우).
  • 루프 형성 및 간단한 계산 루프 최적화 (즉, 루프 본문의 측면 출구 없음). 이러한 루프의 경우 확장 유도 변수를 기반으로하는 배열 액세스가 최적화되어 루프 프롤로그에서만 null 및 범위 검사가 수행됩니다.
  • 런타임시 동적 패치가있는 가상 callsite 당 하나의 인라인 인라인 캐시.
  • mul/div에 대한 리터럴 피연산자의 전력 감소와 같은 옹홀 최적화.

진저 브레드에서는 게터/세터에 간단한 인라이닝을 추가했습니다. 기본 JIT 프론트 엔드는 여전히 간단한 추적 기반이므로, 호출 수신자가 거기에 분기를 가지면 인라인되지 않습니다. 그러나 가상 getter/setter가 문제없이 인라인 될 수 있도록 인라인 캐시 메커니즘이 구현됩니다.

우리는 현재 컴파일러가 코드 분석 및 최적화를위한 더 큰 창을 갖도록 간단한 추적 이상으로 컴파일 범위를 확대하고 있습니다. 계속 지켜봐.

+1

공유해 주셔서 감사합니다. –

+11

당신은 특별히 이것을 답변하기 위해 등록 했습니까? 고맙습니다! Gingerbread를 내놓기에는 통신 사업자들이 너무 느리다. 적어도 내가 생각하기에 그 최적화에 의지 할 수는 없다. 이것은 모든 좋은 것들이지만, 저는 컴파일러 작가가 아니기 때문에 실제로 적용하는 방법을 보는데 어려움을 겪고 있습니다. 특히 : ... – Thomas

+2

(1) 루프의 상한선이 최종 변수가 아닌 변수 (예 : 필드)에 의존하거나 최종 로컬 변수에 상한값을 저장해야합니까? (2) 반복적으로 액세스되는 모든 필드에 대해 동일한 질문. (3) 가능하다면 내 방법을 '최종'이라고 선언해야합니까? 또는 여전히 가상 전화 사이트로 간주됩니까? (4) 인라인은 일반적으로 JIT 수준에서 수행되지 않지만 어쩌면 컴파일러 및/또는 DX 도구로 수행하는지 여부를 알 수 있습니다. – Thomas

10

내 대답은 당신의 모든 질문에 대답하지 않을 것이라는 확신하지만 그것도 하나의 답을 경우이 승리 같아요.

주제에 대한 깊은 지식이있는 것으로 보이고 원하는 것을 알고 있으므로 다음을 수행 할 수 있습니다. 조사하고자하는 측면을 포함하는 예제 응용 프로그램을 빌드하십시오.

APK를 가져 와서 APK Tool을 통해 실행하십시오. 자신이 작성한 코드를 리버스 엔지니어링하면 원하는대로 처리 할 수 ​​있습니다.

APK 도구가 리소스를 추출하고 디코딩하여 .dex 파일을 .smali 개의 파일로 리버스 엔지니어링합니다. 파일 .smali을 읽는 방법과 제한 사항에 대한 자세한 정보를 얻으려면 smali 프로젝트를 찾아보십시오.

다시 한 번 말씀 드리지만이 질문에 모두 답변하지는 않겠지 만 좋은 시작일 수 있습니다.

+1

좋은 대답, 고마워. 그 조사 라인은 나에게 아직 발생하지 않았는데, 그 이유는 주로 많은 시간이 걸리기 때문입니다. 이것은 JITter의 효과가 불확실하지만 최소한 자바 컴파일러와 dx가 수행하는 것을 보여줍니다. 내가 호기심을 느끼고이 길로 내려 가면 분명히 결과를 다시 올릴 것입니다. – Thomas

+0

네, 그렇게하십시오. 나는 결과에 대해 매우 관심이 많다. –

+1

javac는 몇 가지 최적화를 수행하지만 극적인 것은 없습니다. "dx"는 충실한 입력 변환을 제공합니다. Ben이 지적했듯이, 이러한 것들이 사실이 아니라면 디버거로 인해 많은 어려움을 겪을 것입니다. 이에 대한 예를 보려면 http://groups.google.com/group/android-platform/browse_thread/thread/e4749164474fb429/93901e2e43a657c8 (특히 'dx'가 ' -g "를 javac에 추가). 또한 ProGuard의 최적화를 조사해야합니다. – fadden

5

먼저, 나는 dalvik에 대한 전문가가 아니며, 나의 반응 중 일부는 틀릴 수도 있다고 말하면서 머리말을 붙이십시오. 하지만 dalvik에서 JIT 코드를 파헤 쳤고 dalvik이 실행하는 바이트 코드에 대해 잘 알고 있습니다.

  1. 메소드 인라이닝 - 내가 아는 한, 이것은 결코 발생하지 않습니다. 나는 그것이 바이트 코드 레벨에서 결코 일어나지 않는다는 것을 거의 확신하고 있으며, 현재 JIT 레벨에서 일어난다 고 생각하지 않는다.

  2. 일반적인 하위 표현식 제거 - 최종 변수/필드를 사용하지 않는 하위 표현식에 대해서만 수행됩니다. 그때조차도 나는 긍정적으로 생각하지 않는다. 그것이 끝나면, 나는 그것이 바이트 코드 레벨에서, 아마 JIT 레벨에서 끝난다고 기대할 것이다. 배열 조회에서 확인

  3. 경계 - 단서

  4. 값 인라인 - 지금까지 내가 아는 한, 예 - 그들은 그 모든 시나리오에서 인라인 될 것입니다.

  5. 지점 예측 - 확실하지

  6. 간단한 산술 - 아니 지금까지의 내가 또한

알고, 내가 당신에게 접근 방식의 또 다른 수단을 언급하고 싶습니다 - DX와 달빅은 둘 다 오픈 소스이므로 원하는 모든 것을 파고들 수 있습니다. 그들은 분명히 작은 코드베이스가 아니기 때문에 분명히 그 수준에서 파고 들려고 노력할 것입니다.

+0

글쎄,이게 무슨 일이라도 있다면, 나는 내 방식을 손으로 인라인하고 서브 표현식 결과를 캐싱하는데 잘 해왔다. 감사! – Thomas

관련 문제