안드로이드의 가상 머신 튜닝 성능 최적화

안드로이드 응용 프로그램은 자바 가상 머신에서 실행되며 자바 GC와 언어입니다. 가비지 컬렉션은 가상 머신에서 STW라고하는 것은 매우 이미지를 수행 할 때 (세계를 중지), 즉 말을하는 것입니다 더 이상 사용하지 않는 이러한 개체를 복구하기 위해, 가상 머신은 필요를 만들기 위해 모든 스레드를 중지해야합니다 일. 이 런타임 ART에 큰 개선, 그러나 GC 성능 앱 런타임의 존재 왔지만 항상 미묘한 효과가 있습니다. 당신이 전화 로그 입력을 통해 보면, 당신처럼 보이는 부분을 볼 수 있습니다 :

12-23 18 : 46 : 07.300 28643-28658 /? I / 아트 : 배경 GC 자유, 32메가바이트 / 33메가바이트 15442 (1천4백킬로바이트) AllocSpace 오브젝트 8 (1백28킬로바이트) LOS 오브젝트 4 % 해방 스티커 동시 마크 스윕은 GCDaemon 스레드 CareAboutPauseTimes에 10.356ms 전체 53.023ms 일시 중지 1
12-23 18시 46분 : 12.250 28643-28658 /? I / 아트 : 배경 GC 자유, 31메가바이트 / 35메가바이트 28,723 (1천8백56킬로바이트) AllocSpace 객체 6 (92킬로바이트) LOS 개체, 11 % 해제 부분 컨 커런트 마크 스윕은 2.380ms에게 일시 총 108.502ms을 GCDaemon 스레드 CareAboutPauseTimes 1에서

GC 가격에 제공 : 위의 로그는 사실을 반영한다. "메모리 누수를 방지"가 성능 튜닝 언급 GC에 대한 많은 기사가 가비지 수집 프로세스에 대한 장황한 연설뿐만 아니라 원리를 보낼 것입니다,하지만 전략은 "불필요한 개체를 만들 수 없습니다"보다 아무것도하지 않았다 최종은, LeakCanary을 MAT를 언급 도구의 사용이 올라가 같은; 난 단지 아주 창백하고 약한 것을 말할 수있다 - 기본적인 요구해야 도구를 사용하는 방법을 배우게, 코드를 작성합니다.

안드로이드 NDK도 개발을 지원하지만, 우리는 바로, C ++ 전체 재 작성의 모든 코드를 삽입 할 수는 없지만? 그래서, 우리는 할 수있는 방법이 없다 GC의 전략에 영향을 미치는 , 그것을 최소화하기 위해 GC를 만드는? 대답은 '예'입니다. 각 앱 자체 프로세스 공간에서 별도의 가상 머신 인스턴스, 우리는 상당한 주도권을 가지고이 앱 - 원리는 안드로이드의 프로세스 메커니즘입니다.

나 간단한 예를 들어 보겠습니다. (안드로이드 5.1 시스템을 기반으로 다음의 내용은, 모든 원리와 코드가 보장되지는 시스템의 다른 버전에서, 심지어 ROM에서 작동합니다)

모든 프로세스는 응용 프로그램이 Zygote의 과정 포크에서 제공하고, 프로세스 공간 Zygote의 프로세스를 공유 쓰기 메커니즘에 안드로이드 사본에 앱을 사용하여 자식 프로세스, 그리고 안드로이드 런타임 안드로이드 시스템 시작이 프로세스가 Zygote의를 생성되어있는 가상 머신을 생성 완료했다. 가비지 콜렉션은 그러므로, 우리는 시작 프로세스 접합체 과정에 대해 이야기를 시작, 가상 머신의 일부입니다.

우리는, 안드로이드 시스템은 리눅스 커널, 리눅스 시스템을 기반으로 알고, 모든 프로세스가 init 프로세스 과정의 후손, 접합체 프로세스는 init 프로세스에 의해 생성 시스템 시작의 과정에, 예외는 아니다. 시스템 시작 스크립트 시스템 / 코어 / ROOTDIR / init.rc 파일에서, 우리는 Zygote의 과정을 시작하는 스크립트 명령을 볼 수 있습니다 :

서비스 접합자 / 시스템 / 빈 / app_process -Xzygote / 시스템 / 빈 -zygote -start 시스템 서버

구현 / 시스템 / 빈을 통해 그 init 프로세스는 / 접합체 프로세스를 만들 수있는 실행 파일을 app_process, app_process 소스 코드를 볼 수 있습니다 여기에 , 지난 주 기능에서 같은 단어가 :

if (zygote) {
 runtime.start("com.android.internal.os.ZygoteInit", args);
} else if (className) {

마지막에 호출 AndroidRuntime.cppstart 기능,이 기능은 가장 중요한 단계는 가상 머신을 시작하는 것입니다 :

JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
 return;
}

이 기능은 다소 긴하지만, 같은 힙 크기 등과 같은 가상 머신 시작의 분석 매개 변수입니다; largeHeap에게 탐구 이러한 매개 변수에 대한 설명은 가상 시스템에 대해 매우 중요하다 할 몇 가지 중요한 매개 변수이 문서를, 우리는 나중에 볼 수 있습니다. 매개 변수를 구문 분석하는 것은 완료된 후, 마지막 호출은 JNI_CreateJavaVM실제로 자바 가상 머신을 만들 수 있습니다. 이 인터페이스는 달빅은 종래 기술에 광범위로 전환 할 수 세 안드로이드 가상 머신 인터페이스에 의해 정의된다. 그것은 특히 지금에 jni_internal.cc : 직접 안드로이드 런타임을 만든 가상 머신의 관련 매개 변수를 얻기 위해이 기능을 후 JNI_CreateJavaVM는;

if (!Runtime::Create(options, ignore_unrecognized)) {
 return JNI_ERR;
}

런타임 힙 앱은 밖으로 생성, GC와 관련되는, 매우 복잡한 만들 수 있습니다, 힙 생성자는 GC에 큰 영향을 미칠 변수의 무리를 받아, GC는 전략을 조정하려면, 여기에서 시작, 그것은 더 신뢰할 수있다.

heap_ = new gc::Heap(options->heap_initial_size_,
 options->heap_growth_limit_,
 options->heap_min_free_,
 options->heap_max_free_,
 options->heap_target_utilization_,
 options->foreground_heap_growth_multiplier_,
 options->heap_maximum_size_,
// ...

heap_initial 어떤 크기 힙의 초기 크기는, heap_growth 한도는 최대 한계 힙 성장, heap_min입니다 무료로 하고 heap_max는 무료로 무엇입니까? 자세한 사용을 참조하십시오 안드로이드 ART GC의 분석 GrowForUtilization를 메모리 조각화 힙을 감소, 힙의 효율성을 보장하기 위해, 단순히 안드로이드 시스템을하며 GC 후에 각각의 실행은 일부 메모리 힙 크기가 조정됩니다 되찾기 위해. 예를 들어, 그림 페이지를 많이하는 100M 메모리에 적용이 시간, 당신이 1 억 자연 회복 된이 페이지를 떠날 때, 사용 가능한 메모리가 입력 있지만 낭비를 방지하기 위해 시스템을 넣지 사용 가능한 메모리 100M은 모든두고 있지만 조정을 할 수 있습니다. 특정 얼마 후 조정 heap_min_free_, heap_max_free_뿐만 아니라 heap_target_utilization_관련.

설명의 여기, 원칙이되었습니다 부분은 이상이고 공정뿐만 아니라 약간 더 복잡하다에 어려움이 없습니다. 그런 다음 힙, 우리의 성능 최적화로 시작하는 것이 무슨 상관입니까?

시작 안드로이드 앱 동안, 시간이 지남에 따라 프로세스 메모리가 증가되고, 초기 크기가 8M입니다 힙을 가정 30M의 시작시 메모리 피크를 차지, 일시적으로 많은 수의 개체와 함께 과정을 부팅 생성, 그들은 Chaosheng 사이는 죽을 곧 복구 할 수 있습니다 :

위와 같이, 이것은 메모리 사용량 앱 시작하는 동안 특정 시간이고 우리는 짧은 라인을 많이 보았다, 전문 용어는 지터 메모리라고합니다, 이유, 우리는 또한 매우 명확하다 - 만든 임시 개체가 많이있다. 어떻게 해결? 어떤 사람들은 일시적으로 많은 수의 개체를 생성하지 않습니다 말한다. 나는 모든 진실을 알고 있지만 수 없습니다. 많은 대형 응용 프로그램의 경우, 과정은 매우 복잡 시작, 많은 작업을 간단하게 제거 삭제할 수 없습니다. 그래서 질문은 30M 시스템이 너무 공황 왜 아주 많은 수는되지이지만, 또한 메모리를 복구 떨어지고 유지해야합니까?

당신의 어머니라는 추운 것 같아요 감기가 있습니다. 가비지 콜렉션은 복구 가기 전에 쓰레기가 말을하지만, 한 기분으로 시스템이 쓰레기 할 필요가 있다는 없습니다.

글쎄, 그것없이 지속적인 성장을 유지하기 위해 부팅 프로세스 힙 GC 동안 허용 될 수없는 이유는 무엇입니까? 결국, 30M은 OOM 발생하지 않습니다합니다. 어떤 시스템이 그렇게하지 않는 원인은? 대답은 사용 가능한 메모리입니다. 예를 들어, 24M로 성장 부팅 프로세스 힙의 진행과 더불어, 시작 힙 8M가,이 시간은 GC를 수행, 또한 힙 16M로 돌아 손실 8M 메모리를 복구 우리는 사용 가능한 메모리 8M 있습니다. 말할 것이다 시스템, 젊은이, 당신은 그 일을 너무 많이 사용 가능한 메모리입니다 복용? 엄마는 유지할 수 있도록, 그래서 당신은 무료 2M의 메모리입니다 떠났다. 그러나 분명히 힙 메모리 응용 프로그램의 사용은 곧 18M 이상의 것, 그래서 그는 메모리를 완료하기 위해 부드러운 시작될 때까지 계속해서, GC와 힙 크기 조정의 시리즈를 시작했다. 지금까지, 우리는 아주 명확한 결론되었습니다 :

우리가 heap_min 조절할 수있는 경우 무료로 하고 heap_max 무료로 크게 GC의 과정에 영향을 미칠 수있을 것입니다

어떻게이 두 가지 매개 변수 그것의 크기를 조정? 힙 포인터가 직접 메모리를 수정할 수 있으며,이 두 가지 매개 변수의 오프셋을 찾을 개체를 얻기 위해 여기에 C ++ 메모리 레이아웃에 대한 지식이 조금 필요, 객체에 힙 포인터를 얻는 방법에 관해서는, 단지 소스 코드 내에서 답을 찾을 수 있습니다. 여기에 최종 구현 코드를 제공합니다 :

void modifyHeap(unsigned size) {
 // JavaVMExt指针 可以从JNI_OnLoad中拿到 
 JavaVMExt * vmExt = (JavaVMExt *)g_javaVM;
 if (vmExt->runtime == NULL) {
 return;
 }
 char* runtime_ptr = (char*) vmExt->runtime;
 void** heap_pp = (void**)(runtime_ptr + 188);
 char* c_heap = (char*) (*heap_pp);

 char* min_free_offset = c_heap + 532;
 char* max_free_offset = min_free_offset + 4;
 char* target_utilization_offset = max_free_offset + 4;

 size_t* min_free_ = (size_t*) min_free_offset;
 size_t* max_free_ = (size_t*) max_free_offset;

 *min_free_ = 1024 * 1024 * 2;
 *max_free_ = 1024 * 1024 * 8;
}

아래 시작 프로세스의 메모리 사용량을 수정 한 후, 우리는 우리의 목적이 달성 된 것을 볼 수 있습니다 :

또한, 위의 코드는 프리젠 테이션의 역할을, 휴대 성 및 호환성 중 하나를 고려하지 않습니다. 정말 사용에 넣어 실제 작업은 다음과 같습니다 첫째, 우리는 서로 다른 버전에서 다를 수 있습니다 멤버 변수를 상쇄 안드로이드의 클래스의 특정 버전의 메모리 레이아웃에 의존하고, 둘째, 분, 무료로 및 최대가 무료로 특정 조정 휴대 전화의 물리적 메모리, 메모리, 휴대 전화의 앱 사용과 구성 요인 중 초기 힙 크기에 관련된 얼마나 가깝게, 매개 변수의 적절한 조정은 약간의 시간이 소요, 안드로이드 모델은 너무 여기에 몇 가지 요령이 필요합니다.

不知道上面这个例子有木有让你感受到深入系统底层,那种呼风唤雨无所不能的快感?可能很多人觉得我们都是写写if else而已,调节面改动画写业务已经够了;但我想说明的是,深入学习系统原理是非常有好处的,它可以赋予你在应用层永远无法拥有的能力。

自己是从事了七年开发的Android工程师,不少人私下问我,2019年Android进阶该怎么学,方法有没有?

没错,年初我花了一个多月的时间整理出来的学习资料,希望能帮助那些想进阶提升Android开发,却又不知道怎么进阶学习的朋友。【包括高级UI、性能优化、架构师课程、NDK、Kotlin、混合式开发(ReactNative+Weex)、Flutter等架构技术资料】,希望能帮助到您面试前的复习且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

资料获取方式:加入Android架构交流QQ群聊:513088520 ,进群即领取资料!!!

点击链接加入群聊【Android移动架构总群】:加入群聊

资料大全

추천

출처blog.csdn.net/weixin_43351655/article/details/91491457