앱이 사용할 수있는 최대 RAM 양은 얼마입니까?


145

Android 운영 체제메모리 관리 와 관련 하여이 질문에 대해 궁금한 점이 있으므로 해당 주제에 대한 자세한 답변을 바랍니다.

내가 알고 싶은 것 :

  • Android 애플리케이션 (시스템 앱이 아님)이 사용할 수 있는 최대 메모리 양 ( 메가 바이트 / 총 RAM의 백분율 )은 얼마입니까?
  • 안드로이드 버전 간에 차이가 있습니까?
  • 장치 제조업체 와 관련하여 차이가 있습니까?

그리고 가장 중요한 것은 :

  • 무엇 간주됩니다 / 가에 의존하는 일 이 응용 프로그램 실행시에 사용할 수있는 RAM의 양을 결정하는 시스템에 올 때 (응용 프로그램 당 메모리의 최대 정적 번호가 아닙니다 가정)?

내가 지금까지들은 내용 (2013 년까지) :

  • 초기 Android 기기의 앱당 한도는 16MB입니다.
  • 나중에이 한도는 24MB 또는 32MB로 증가했습니다.

나를 매우 궁금하게 만드는 것은 :

이 두 한계는 매우 낮습니다.

최근에 장치 RAM을 확인하기 위해 Android 작업 관리자 를 다운로드했습니다 . 내가 주목 한 것은 약 40-50 메가 바이트의 RAM을 사용하는 응용 프로그램이 있다는 것입니다.이 응용 프로그램은 언급 된 최대 RAM 사용량보다 32MB라고합니다. 그렇다면 Android는 앱이 사용할 수있는 RAM의 양을 어떻게 결정합니까? 앱이 한도를 초과 할 수 있습니까?

또한 약 30-40 메가 바이트를 사용할 때 OutOfMemoryException이 발생하는 일부 응용 프로그램이 충돌합니다 (시스템에 의해 죽었습니까?) . 다른 한편으로, (메모리 누수로 인해) 추락하거나 죽지 않는 시간이 지나면 (메모리 누수로 인해) 100MB 이상 을 사용하여 휴대 전화에서 실행되는 앱 이 있습니다. 따라서 얼마나 많은 RAM을 절약 할 수 있는지 결정할 때 앱 자체에 따라 달라집니다 . 이것이 어떻게 가능한지? (저는 768MB RAM의 HTC One S로 테스트를 수행했습니다)

면책 조항 : 나는 어떤 방식 으로든 안드로이드 작업 관리자 응용 프로그램과 관련이 없습니다.

답변:


119

Android 애플리케이션 (시스템 앱이 아님)이 사용할 수있는 최대 메모리 양 (메가 바이트 / 총 RAM의 백분율)은 얼마입니까?

장치마다 다릅니다. getMemoryClass()onActivityManager 은 코드가 실행되는 장치의 값을 제공합니다.

안드로이드 버전간에 차이가 있습니까?

예, 수년 동안 OS 요구 사항이 증가하고 장치가 일치하도록 조정되는 한.

장치 제조업체와 관련하여 차이가 있습니까?

예, 제조업체가 장치를 제조하는 한 크기는 장치마다 다릅니다.

앱이 사용할 수있는 RAM의 양을 결정할 때 고려해야 할 "부족 요인"은 무엇입니까?

나는 "부작용"이 무엇을 의미하는지 전혀 모른다.

초기 장치의 앱당 한도는 16MB입니다. 이후 장치는 24MB 또는 32MB로 증가

맞습니다. 해상도가 높을수록 비트 맵이 커지므로 화면 해상도는 결정적인 요소이므로 태블릿 및 고해상도 전화기의 값은 더 높은 경향이 있습니다. 예를 들어, 48MB 힙을 가진 장치가 표시되며 그보다 높은 값이 있으면 놀라지 않을 것입니다.

앱이 한도를 초과 할 수 있습니까?

해당 앱의 작성자가 자신이하는 일을 알고 있다고 가정합니다. 핵심 안드로이드 엔지니어가 앱의 메모리 사용이 어렵다는 것을 고려할 때 , 해당 앱이 반드시 정확한 결과를 제공한다고 가정하지는 않습니다.

즉, 네이티브 코드 (NDK)에는 힙 제한이 적용되지 않습니다. 또한 Android 3.0부터 앱은 일반적으로 수백 MB 범위의 "대형 힙"을 요청할 수 있지만 대부분의 앱에서 잘못된 형식으로 간주됩니다.

또한 약 30-40 메가 바이트를 사용할 때 일부 앱이 OutOfMemoryException으로 충돌하는 것으로 나타났습니다.

Android 가비지 수집기는 압축 가비지 수집기가 아닙니다. 예외는 실제로이어야 CouldNotFindSufficientlyLargeBlockOfMemoryException하지만 아마도 너무 장황한 것으로 간주되었습니다. 요청한 블록을 할당OutOfMemoryException수없고 힙을 완전히 소모하지 않았 음을 의미합니다.


나는 테이블에 대해 이해할 수 없으며, 해상도가 1080 x 1920 인 해상도가 Xperia X mobile이고 해상도가 800 x 1280 인 다른 장치 Samsung Tab 4가 있으므로 동일한 램 점령이 필요합니다. 3GB RAM과 탭에는 1.5GB RAM이 함께 제공되므로 큰 화면으로 인해 태블릿이 큰 램을 차지합니까?
Rahul Mandaliya

@RahulMandaliya : 죄송 합니다만 귀하의 우려 사항 또는이 질문과 관련이 있는지 이해가되지 않습니다. 우려 사항에 대해 자세히 설명하는 별도의 스택 오버플로 질문을 열 수도 있습니다.
CommonsWare

15

2018 년 말이 되서 상황이 바뀌 었습니다.

우선 : 앱을 실행하고 Android Studio에서 Android 프로파일 러 탭을 엽니 다. 당신은 얼마나 많은 메모리를 소비하는지 볼 것입니다, 당신은 놀랄 것이지만 많은 RAM을 할당 할 수 있습니다.

또한 여기에는 메모리 관리에 대한 심층적 인 모양을 제공 할 수있는 메모리 프로파일 러 사용 방법에 대한 자세한 지침이 포함 된 공식 문서의 유용한 기사 가 있습니다.

그러나 대부분의 경우 일반 Android 프로파일 러로 충분합니다.

여기에 이미지 설명을 입력하십시오

일반적으로 앱은 50Mb의 RAM 할당으로 시작하지만 메모리에 일부 사진을로드하기 시작하면 즉시 90Mb까지 점프합니다. 미리로드 된 사진 (각각 3,5Mb)이있는 ViewPager로 활동을 열면 몇 초 만에 190Mb를 쉽게 얻을 수 있습니다.

그러나 이것이 메모리 관리에 문제가 있다는 것을 의미하지는 않습니다.

내가 줄 수있는 최선의 조언은 가이드 라인과 모범 사례를 따르고 이미지 로딩을 위해 최고의 라이브러리를 사용하는 것입니다 (Glide, Picasso).


그러나 무언가를 조정해야하고 실제로 수동으로 할당 할 수있는 메모리 양을 알아야하는 경우 총 여유 메모리를 확보하고 사전 결정된 부분 (%)을 계산할 수 있습니다. 필자의 경우, 해독 된 사진을 메모리에 캐시해야했기 때문에 사용자가 목록을 슬라이드 할 때마다 해독 할 필요가 없습니다.

이를 위해 LruCache 클래스 를 사용할 수 있습니다 . 그것은 객체가 얼마나 많은 메모리를 할당했는지 (또는 인스턴스 수)를 자동으로 추적하고 최근 사용 내역으로 최신을 유지하기 위해 가장 오래된 메모리를 제거하는 캐시 클래스입니다. 다음은 사용법에 대한 훌륭한 자습서입니다.

필자의 경우 엄지와 첨부 파일을 위해 두 개의 캐시 인스턴스를 만들었습니다. 싱글 톤 액세스로 정적으로 만들었으므로 전 세계 앱에서 사용할 수 있습니다.

캐시 클래스 :

public class BitmapLruCache extends LruCache<Uri, byte[]> {

    private static final float CACHE_PART_FOR_THUMBS_PRC = 0.01f; // 1% (Nexus 5X - 5Mb)
    private static final float CACHE_PART_FOR_ATTACHMENTS_PRC = 0.03f;// 3% (Nexus 5X - 16Mb)
    private static BitmapLruCache thumbCacheInstance;
    private static BitmapLruCache attachmentCacheInstance;

public static synchronized BitmapLruCache getDecryptedThumbCacheInstance() {
    if (thumbCacheInstance == null) {

        int cacheSize = getCacheSize(CACHE_PART_FOR_THUMBS_PRC);
    //L.log("creating BitmapLruCache for Thumb with size: " + cacheSize + " bytes");
        thumbCacheInstance = new BitmapLruCache(cacheSize);
        return thumbCacheInstance;
    } else {
        return thumbCacheInstance;
    }
}

public static synchronized BitmapLruCache getDecryptedAttachmentCacheInstance() {
    if (attachmentCacheInstance == null) {

        int cacheSize = getCacheSize(CACHE_PART_FOR_ATTACHMENTS_PRC);
    //            L.log("creating BitmapLruCache for Attachment with size: " + cacheSize + " bytes");
        attachmentCacheInstance = new BitmapLruCache(cacheSize);
        return attachmentCacheInstance;
    } else {
        return attachmentCacheInstance;
    }
}

private BitmapLruCache(int maxSize) {
    super(maxSize);
}

public void addBitmap(Uri uri, byte[] bitmapBytes) {
    if (get(uri) == null && bitmapBytes != null)
        put(uri, bitmapBytes);
}

public byte[] getBitmap(Uri uri) {
    return get(uri);
}


@Override
protected int sizeOf(Uri uri, byte[] bitmapBytes) {
    // The cache size will be measured in bytes rather than number of items.
    return bitmapBytes.length;
}
}

이것은 사용 가능한 여유 RAM을 계산하는 방법과 그것을 얼마나 많이 물릴 수 있는지입니다.

private static int getCacheSize(float partOfTotalFreeMemoryToUseAsCache){
    final long maxMemory = Runtime.getRuntime().maxMemory();
    //Use ... of available memory for List Notes thumb cache
    return (int) (maxMemory * partOfTotalFreeMemoryToUseAsCache);
}

그리고 이것은 캐시 된 이미지를 얻기 위해 어댑터에서 사용하는 방법입니다.

byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);

백그라운드 스레드에서 캐시로 설정하는 방법 (일반 AsyncTask) :

BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes); 

내 앱은 API 19 이상을 대상으로하므로 장치가 오래되지 않았으며 사용 가능한 RAM 의이 부분은 내 경우에는 캐시에 충분합니다 (1 % 및 3 %).

재미있는 사실 : Android에는 앱에 할당 된 메모리 양을 가져 오는 API 또는 기타 해킹이 없으며 다양한 요소를 기반으로 즉시 계산됩니다.


추신 : 나는 정적 클래스 필드를 사용하여 캐시를 보유하고 있지만 최신 Android 지침에 따라 해당 목적으로 ViewModel 아키텍처 구성 요소 를 사용하는 것이 좋습니다 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.