아주 작은 메모리를 사용하는 이유, 그것은 또한 GC?

Java 가상 머신에 내장 된 안드로이드 어플, 구글 동시에 적시에 웨이크 실행 APP을 보장하기 위해, 그것은 당신이 여러 매개 변수에 의해 ADB 명령을 볼 수 있습니다, 각 가상 머신에 대한 최대 사용 가능한 메모리를 설정

* [dalvik.vm.heapgrowthlimit]: [192m]
* [dalvik.vm.heapmaxfree]: [8m]
* [dalvik.vm.heapminfree]: [512k]
* [dalvik.vm.heapsize]: [512m]
* [dalvik.vm.heapstartsize]: [8m]
* [dalvik.vm.heaptargetutilization]: [0.75]

사용할 수있는 메모리의 최대량이다 Dalvik.vm.heapsize는,이 값이 설정의 개선과 박리와 벤더와의 관계를 가지고 서서히 dalvik.vm.heapsize되는 최대 메모리를 사용할 수있는 가상 머신 때문에 증가하고, 그래서 응용 프로그램 메모리의 시간은 최대 GC 것이 최대 아닌가요? 대답은 확실히 아니, 우리는 낮은 메모리 사용 시간, 그림 APP 런타임 상황을 참조 GC됩니다에, 곡선의 관점에서 검토한다 :

차트에서 보면, 1,2,3 세 점은 GC에서 자리를 차지하게 될 것 같다,하지만이 시간이 아니라 매우 높은 점유율 APP 메모리, 최대 메모리는 여전히 장거리, 그것은이 시간이 일어날 이유 메모리 당신은 GC 전에 최대 메모리 때까지 기다렸다 경우 GC는, 사실, 직관적이고 쉽게는, 이해 않고, 다음 두 가지 단점이있을 것이다 : 감소 된 시스템 성능의 결과로 첫째, 자원의 메모리 낭비, 둘째, 더 큰 메모리 풋 프린트, 더 많은 소비 GC 긴 피해야한다. 결국 것을 GC 시간? 항상 할당 된 메모리 블록이 GC를 될 것입니다되지 않으며,이 또한 부정적이어야한다, 우리는 단순히 메모리 할당, GC, 메모리 증가 아래의 메커니즘을 이해해야한다.

안드로이드 달빅 가상 머신 할당 및 GC

가상 머신의 구성 매개 변수의 중요성에 먼저 모습 만 dalvik.vm.heapstartsize을 알려줍니다 위, 최대 메모리 크기를 적용하는 것입니다,

  • dalvik.vm.heapgrowthlimit 및 dalvik.vm.heapsize는, 자바 가상 머신의 최대 메모리 한계입니다 일반적으로 heapgrowthlimit <힙 크기, 매니페스트 응용 프로그램의 레이블 안드로이드에 선언 된 경우 : largeHeap는 = "true"로, APP 힙 크기까지만 OOM, 또는 OOM은 heapgrowthlimit에 도달 할 것
  • 초기 힙 크기 dalvik.vm.heapstartsize 자바, 다시 시스템 부팅시 시스템에 물리적 메모리 Davlik 가상 머신 응용 프로그램의 크기를 지정하고 MAX에 도달 할 때까지 점차적으로, 필요에 따라 더 많은 실제 메모리를 적용
  • GC 후 최소 여유 힙 값을 dalvik.vm.heapminfree
  • dalvik.vm.heapmaxfree 힙 최대 유휴 값
  • dalvik.vm.heaptargetutilization 힙 목표 이용

세 후자의 값은 각 후 Java 힙 GC가 사용 된 메모리 및 사용 가능한 메모리가 적절한 비율을 가지고 있는지 확인하기 위해, 그래서 당신은 GC, 힙 활용 U의 수를 줄이기 위해 시도 할 수 있습니다, 최소 여유 최소 유휴 바이트, 최대입니다 MaxFree 아이들 바이트는 일정 시간 후 GC가 생존 LiveSize 물체에 의해 점유 된 메모리의 크기 인 것으로한다. 그래서 이번에는 힙 (LiveSize / U)을위한 이상적인 크기 여야합니다. 그러나 (LiveSize / U가) 또는 (LiveSize + MinFree 사용) 및 이하 (LiveSize + MaxFree가), 그렇지 않으면 조정이 필요한 동일한 사실, 조정 softlimit 소프트 캡보다 커야합니다

static size_t getUtilizationTarget(const HeapSource* hs, size_t liveSize)
{
    size_t targetSize = (liveSize / hs->targetUtilization) * HEAP_UTILIZATION_MAX;

    if (targetSize > liveSize + hs->maxFree) {
        targetSize = liveSize + hs->maxFree;
    } else if (targetSize < liveSize + hs->minFree) {
        targetSize = liveSize + hs->minFree;
    }
    return targetSize;
}

이들은, 가정 liveSize = 150M, targetUtilization = 0.75 maxFree = 8 MINFREE = 512K, 다음 이상적 크기 200M 소스 계산식이고, 200M 후, 이번에는 (150) + (8)보다 훨씬 더 스택 크기를 조정해야 158M,이 softLimit가 필요한 응용 프로그램 메모리는 GC의 중요한 지표인지, 다음 시나리오를 고려 옆에 부드러운 캡입니다 :

장면 하나 : 현재는 softLimit = 158M, liveSize = 150M, 이번 경우, 필요는 100K 메모리 개체를 할당

현재의 상한은 158M이다 인해에 8-100K> 512K, 메모리를 조정할 필요가 없습니다,이 시간, GC가 존재하지 않는 메모리를하기 때문에, 메모리는, 분배 한 후, 직접 성공에 할당 할 수 있습니다

장면 두 : 현재 softLimit = 158M, liveSize = 150M, 이번 경우, 메모리를 할당 할 필요는 7.7M이다

현재의 상한은 158M이다 인해에 여유 메모리 8-7.7M <512K, 그것은 GC에 필요하기 때문에, 메모리는 softLimit을 조정하는 동안, 배포 후, 성공에 직접 할당 할 수 있습니다

장면 세 : 현재는 softLimit = 158M, liveSize = 150M, 이번 경우, 메모리를 할당 할 필요가 10M입니다

由于当前的上限是158M,内存分配失败,需要先GC,GC之后调整softLimit,再次请求分配,如果还是失败,将softLimit调整为最大,再次请求分配,失败就再GC一次软引用,再次请求,还是失败那就是OOM,成功后要调整softLimit

所以,Android在申请内存的时候,可能先分配,也可能先GC,也可能不GC,这里面最关键的点就是内存利用率跟Free内存的上下限,下面简单看源码了解下堆内存分配流程:

   static void *tryMalloc(size_t size)
    {
        void *ptr;
        <!--1 首次请求分配内存-->
        ptr = dvmHeapSourceAlloc(size);
        if (ptr != NULL) {
            return ptr;
        }
        <!--2 分配失败,GC-->
        if (gDvm.gcHeap->gcRunning) {
            dvmWaitForConcurrentGcToComplete();
        } else {
          gcForMalloc(false);
        }
        <!--再次分配-->
        ptr = dvmHeapSourceAlloc(size);
        if (ptr != NULL) {
            return ptr;
        }
         <!--还是分配失败,调整softLimit再次分配-->
        ptr = dvmHeapSourceAllocAndGrow(size);
        if (ptr != NULL) {
            size_t newHeapSize;
       <!--分配成功后要调整softLimit-->
            newHeapSize = dvmHeapSourceGetIdealFootprint();
            return ptr;
        }
         <!--还是分配失败,GC力加强,回收soft引用,-->
        gcForMalloc(true);
        <!--再次请求分配,如果还是失败,那就OOM了-->
        ptr = dvmHeapSourceAllocAndGrow(size);
        if (ptr != NULL) {
            return ptr;
        }
        dvmDumpThread(dvmThreadSelf(), false);          return NULL;  
        }

总结

本文主要说的一个问题就是,为什么不等到最大内存在GC,以及普通GC的可能时机,当然,对于内存的GC是更加复杂的,不在本文的讨论范围之内,同时这个也解释频繁的分配大内存会导致GC抖动的原因,毕竟,如果你超过了maxFree ,就一定GC,有兴趣可以自行深入分析。

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

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

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

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

资料大全

추천

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