Dalvik 및 Android 툴체인에서 어떤 최적화를 기대할 수 있습니까?
저는 고성능 Android 애플리케이션 (게임)을 작업 중이며 먼저 가독성을 위해 코딩하려고하지만 내부에서 일어나는 일에 대한 그림을 마음 속에 간직하고 싶습니다. C ++를 사용하여 컴파일러가 나를 위해 무엇을 할 것인지,하지 않을 것인지에 대해 상당히 좋은 직관을 개발했습니다. Java / Android에 대해 동일한 작업을 시도하고 있습니다.
따라서이 질문. 웹에서이 주제에 대해 거의 찾을 수 없습니다. Java 컴파일러, Dalvik 변환기 (dx) 및 / 또는 JITter (Android 2.2 이상)가 다음과 같은 최적화를 수행합니까?
메서드 인라인. 어떤 조건에서?
private
메소드는 항상 안전하게 인라인 될 수 있습니다. 이게 끝날까요? 방법은public final
어떻습니까? 다른 클래스의 객체에 대한 메서드?static
행동 양식? 컴파일러가 객체의 런타임 유형을 쉽게 추론 할 수 있다면 어떨까요? 나는 등의 방법으로 선언해야final
또는static
가능하면?공통 하위 표현식 제거. 예를 들어
someObject.someField
두 번 액세스 하면 조회가 한 번만 수행됩니까? 게터에게 전화하면 어떻게 되나요? 어떤 산술 식을 두 번 사용하면 어떨까요? 한 번만 평가됩니까? 값이 변경되지 않는 것으로 알고있는 일부 표현식의 결과를for
루프 의 상한으로 사용하면 어떻게됩니까?배열 조회에 대한 경계 검사. 툴체인은 전형적인
for
루프 와 같은 특정 조건에서 이것을 제거 합니까?가치 인라인. 일부에 대한 액세스는
public static final int
항상 인라인됩니까? 다른 수업에 있더라도? 다른 패키지에 있더라도?분기 예측. 이것이 얼마나 큰 문제입니까? 일반적인 Android 장치에서 분기가 큰 성능 저하를 일으키고 있습니까?
간단한 산술. 윌
someInt * 2
로 대체someInt << 1
?
기타 ...
JIT @ Google에서 일하는 엔지니어 중 한 명인 Ben입니다. Bill과 내가이 프로젝트를 시작했을 때 목표는 리소스 경합 (예 : 메모리 풋 프린트, 컴파일러 스레드에 의해 CPU 하이재킹)에 미치는 영향을 최소화하면서 가능한 한 빨리 작동하는 JIT를 제공하여 저가형 장치에서 실행될 수 있도록하는 것이 었습니다. 잘. 따라서 우리는 매우 원시적 인 추적 기반 모델을 사용했습니다. 즉, JIT 컴파일러에 전달 된 컴파일 엔티티는 기본 블록이며 때로는 단일 명령어만큼 짧습니다. 이러한 추적은 인터프리터 및 코드 캐시 조회가 자주 호출되지 않도록 연결이라는 기술을 통해 런타임에 함께 연결됩니다. 어느 정도 속도 향상의 주요 원인은 자주 실행되는 코드 경로에서 반복되는 인터프리터 구문 분석 오버 헤드를 제거하는 데 있습니다.
즉, Froyo JIT로 구현 된 몇 가지 로컬 최적화가 있습니다.
- 레지스터 할당 (JIT가 Thumb 코드를 생성하므로 v5te 대상에 대해 8 개 레지스터 / v7에 대해 16 개 레지스터)
- 스케줄링 (예 : Dalvik 레지스터에 대한 중복 ld / st 제거,로드 호이 스팅, 매장 싱킹)
- 중복 null 검사 제거 (이러한 중복이 기본 블록에서 찾을 수있는 경우).
- 단순 계수 루프에 대한 루프 형성 및 최적화 (즉, 루프 본체에 측면 출구 없음). 이러한 루프의 경우 확장 유도 변수를 기반으로하는 배열 액세스가 최적화되어 널 및 범위 검사가 루프 프롤로그에서만 수행됩니다.
- 런타임시 동적 패치가있는 가상 호출 사이트 당 하나의 항목 인라인 캐시.
- mul / div에 대한 리터럴 피연산자에 대한 전력 감소와 같은 틈새 최적화.
Gingerbread에서 getter / setter를위한 간단한 인라인을 추가했습니다. 기본 JIT 프런트 엔드는 여전히 단순한 추적 기반이므로 호출 수신자가 거기에 분기가 있으면 인라인되지 않습니다. 그러나 인라인 캐시 메커니즘은 가상 게터 / 세터가 문제없이 인라인 될 수 있도록 구현됩니다.
우리는 현재 컴파일러가 코드 분석 및 최적화를위한 더 큰 창을 갖도록 단순한 추적을 넘어 컴파일 범위를 확대하기 위해 노력하고 있습니다. 계속 지켜봐주세요.
내 대답이 모든 질문에 대답하지는 않을 것이라고 확신하지만 하나라도 대답하면 승리라고 생각합니다.
당신은 주제에 대한 심오한 지식을 가지고 있고 당신이 원하는 것을 알고있는 것 같습니다. 그래서 당신은 다음을하고 싶을 것입니다. 조사하려는 측면을 포함하는 예제 애플리케이션을 빌드하십시오.
받은 APK를 가져 와서 APK 도구를 통해 실행합니다 . 의도 한대로 수행하기 위해 자신의 코드를 리버스 엔지니어링하는 것은 우리가 알고있는 것처럼 완벽합니다.
APK 도구는 리소스를 추출 및 디코딩하고 .dex
파일을 .smali
파일로 리버스 엔지니어링 합니다. 파일 을 읽는 방법 과 제한 사항에 대한 자세한 정보를 얻으려면 smali 프로젝트도 검색 할 수 있습니다 .smali
.
다시 말씀 드리지만 이것이 귀하의 모든 질문에 대한 답은 아니지만 좋은 시작이 될 것이라고 확신합니다.
먼저, 내가 dalvik에 대한 전문가가 아니며 내 답변 중 일부가 잘못되었을 수 있다고 말하면서 시작하겠습니다. 하지만 저는 dalvik에서 JIT 코드를 파헤 쳤고 dalvik이 실행하는 바이트 코드에 대해 잘 알고 있습니다.
메소드 인라이닝-내가 아는 한, 이것은 결코 발생하지 않습니다. 나는 그것이 바이트 코드 수준에서는 결코 일어나지 않는다는 것을 거의 긍정적으로 생각한다. 그리고 나는 그것이 미래에있을지라도 현재 JIT 수준에서 일어나지 않는다고 생각한다.
일반적인 하위 표현식 제거-최종적이지 않은 변수 / 필드를 사용하지 않는 하위 표현식에 대해서만 이것이 수행 될 것이라고 생각합니다. 그때도 그런 일이 일어나더라도 전적으로 긍정적 인 것은 아닙니다. 완료되면 JIT 수준이 아닌 바이트 코드 수준에서 수행 될 것으로 예상합니다.
배열 조회에 대한 경계 검사-단서 없음
가치 인라인-내가 아는 한 그렇습니다. 모든 시나리오에서 인라인됩니다.
분기 예측-확실하지 않음
간단한 산술-내가 아는 한 멀지 않음
Also, I'd like to mention another avenue of approach to you - dx and dalvik are both open source, so you can dig into them all you like. Although, they're obviously not small codebases, so would take a fair bit of effort to dig into them at that level
'developer tip' 카테고리의 다른 글
선택적 인수가 제공되었는지 여부를 어떻게 테스트합니까? (0) | 2020.11.11 |
---|---|
개발을 동기화 상태로 유지하기 위해 git-bundle을 사용하는 방법은 무엇입니까? (0) | 2020.11.11 |
AngularJS 템플릿으로 HTML을 렌더링하는 방법 (0) | 2020.11.10 |
라 라벨이 정말 이렇게 느린가요? (0) | 2020.11.10 |
Android Studio에서 모듈 이름을 바꾸시겠습니까? (0) | 2020.11.10 |