RAM สูงสุดที่แอปสามารถใช้คืออะไร?


145

ฉันค่อนข้างสงสัยเกี่ยวกับคำถามนี้เกี่ยวกับการจัดการหน่วยความจำของระบบปฏิบัติการ Androidดังนั้นฉันหวังว่าจะได้คำตอบอย่างละเอียดในหัวข้อนั้น

สิ่งที่ฉันอยากรู้

  • อะไรคือจำนวนเงินสูงสุดของหน่วยความจำ (ในเมกะไบต์ / เป็น ร้อยละของจำนวน RAM) ที่การประยุกต์ใช้ Android (ที่ไม่ได้เป็น app ระบบ) สามารถใช้งานหรือไม่
  • มีความแตกต่างระหว่างเวอร์ชั่น Androidหรือไม่?
  • มีความแตกต่างใด ๆ เกี่ยวกับผู้ผลิตอุปกรณ์หรือไม่

และที่สำคัญที่สุด:

  • อะไรที่ถูกพิจารณา / ขึ้นอยู่กับว่ามันมาถึงระบบเมื่อไรที่แรมใช้งานแอพได้เท่าไร (สมมติว่าหน่วยความจำสูงสุดต่อแอพนั้นไม่ใช่จำนวนคงที่)?

สิ่งที่ฉันเคยได้ยินจนถึง (2013 จนถึง):

  • อุปกรณ์ Android ยุคแรก ๆ มีขนาดสูงสุด 16 เมกะไบต์ต่อแอป
  • หลังจากนี้ขีด จำกัด นี้เพิ่มเป็น 24MB หรือ 32MB

อะไรทำให้ฉันอยากรู้มาก:

ขีด จำกัด ทั้งสองนี้ต่ำมาก

ฉันเพิ่งดาวน์โหลดAndroid Task Managerเพื่อตรวจสอบ RAM อุปกรณ์ของฉัน สิ่งที่ฉันสังเกตเห็นคือมีแอปพลิเคชันที่ใช้ RAM ประมาณ 40-50 เมกะไบต์ซึ่ง obvioulsy มากกว่าการใช้ RAM สูงสุดที่กล่าวถึงคือ 32 MB ดังนั้น Android จะกำหนดจำนวน RAM ที่แอพใช้งานได้อย่างไร? เป็นไปได้อย่างไรที่แอพเกินขีด จำกัด ?

นอกจากนี้ฉันสังเกตเห็นว่าบางแอพของฉันเกิดความผิดพลาด (ถูกฆ่าโดยระบบหรือไม่) ด้วยOutOfMemoryExceptionเมื่อใช้ประมาณ 30-40 เมกะไบต์ ในทางกลับกันฉันมีแอพพลิเคชั่นที่ใช้งานโทรศัพท์ของฉันที่มีขนาด 100 MB ขึ้นไปหลังจากนั้นสักครู่ ดังนั้นจึงเห็นได้ชัดว่ามันยังขึ้นอยู่กับแอพของตัวเองเมื่อมันมาถึงการกำหนดจำนวน RAM ที่จะได้รอด เป็นไปได้อย่างไร? (ฉันทำการทดสอบกับ HTC One S ที่มี RAM 768 MB)

คำเตือน: ฉันไม่มีส่วนเกี่ยวข้องกับแอป Android Task Manager ในทางใดทางหนึ่ง

คำตอบ:


119

จำนวนหน่วยความจำสูงสุด (เป็นเมกะไบต์ / เป็นเปอร์เซ็นต์ของ RAM ทั้งหมด) ที่แอปพลิเคชัน Android (ซึ่งไม่ใช่แอประบบ) สามารถใช้งานได้อย่างไร

ที่แตกต่างกันไปตามอุปกรณ์ getMemoryClass()ในการActivityManagerที่จะทำให้คุณคุ้มค่าสำหรับอุปกรณ์รหัสของคุณกำลังทำงานอยู่กับ

มีความแตกต่างระหว่างเวอร์ชั่น Android หรือไม่?

ใช่ตราบเท่าที่ความต้องการของระบบปฏิบัติการเพิ่มขึ้นในช่วงหลายปีที่ผ่านมาและอุปกรณ์ต้องปรับให้เข้ากับ

มีความแตกต่างเกี่ยวกับผู้ผลิตอุปกรณ์หรือไม่?

ใช่ตราบเท่าที่ผู้ผลิตผลิตอุปกรณ์และขนาดแตกต่างกันไปตามอุปกรณ์

"ปัจจัยด้าน" ใดที่ถูกนำมาพิจารณาเมื่อพิจารณาถึงจำนวน RAM ที่แอปสามารถใช้งานได้

ฉันไม่รู้ว่า "ปัจจัยด้านข้าง" หมายถึงอะไร

อุปกรณ์รุ่นแรกมีขีดสูงสุดต่อแอพที่ 16MB; อุปกรณ์ในภายหลังเพิ่มขึ้นเป็น 24MB หรือ 32MB

ถูกต้องแล้ว ความละเอียดของหน้าจอเป็นปัจจัยสำคัญเนื่องจากความละเอียดที่มากขึ้นหมายถึงบิตแมปที่ใหญ่กว่าดังนั้นแท็บเล็ตและโทรศัพท์ที่มีความละเอียดสูงจะมีค่าสูงกว่า ตัวอย่างเช่นคุณจะเห็นอุปกรณ์ที่มีฮีป 48MB และฉันจะไม่แปลกใจหากมีค่าสูงกว่านั้น

เป็นไปได้อย่างไรที่แอพนั้นเกินขีด จำกัด ?

คุณถือว่าผู้เขียนแอปนั้นรู้ว่าเขากำลังทำอะไรอยู่ เมื่อพิจารณาว่าการใช้หน่วยความจำของแอพเป็นเรื่องยากสำหรับวิศวกรหลัก Android ในการพิจารณาฉันจะไม่คิดว่าแอพที่เป็นปัญหานั้นจำเป็นต้องให้ผลลัพธ์ที่แม่นยำเป็นพิเศษ

ที่ถูกกล่าวว่ารหัสพื้นเมือง (NDK) ไม่อยู่ภายใต้ขีด จำกัด ของฮีป และตั้งแต่ Android 3.0 แอปสามารถขอ "กองขนาดใหญ่" ซึ่งมักจะอยู่ในช่วงหลายร้อย MB แต่นั่นถือว่าเป็นรูปแบบที่ไม่ดีสำหรับแอพส่วนใหญ่

นอกจากนี้ฉันสังเกตเห็นว่าบางแอพของฉันพังด้วย OutOfMemoryException เมื่อใช้ประมาณ 30-40 เมกะไบต์

โปรดทราบว่าตัวรวบรวมขยะ Android ไม่ใช่ตัวรวบรวมขยะแบบย่อ ข้อยกเว้นควรเป็นCouldNotFindSufficientlyLargeBlockOfMemoryExceptionจริง แต่ก็อาจถือว่าเป็นคำที่เกินไป OutOfMemoryExceptionหมายความว่าคุณไม่สามารถจัดสรรบล็อกที่คุณร้องขอได้ไม่ใช่ว่าคุณหมดฮีปทั้งหมดแล้ว


ฉันไม่เข้าใจเกี่ยวกับตารางฉันมี Xperia X mobile ที่มีความละเอียดประมาณ 1080 x 1920 ซึ่งเป็นความละเอียดขนาดใหญ่และอุปกรณ์อื่น Samsung Tab 4 ที่ความละเอียดอยู่ที่ 800 x 1280 ดังนั้นจึงยึดครอง RAM เดียวกันโปรดแนะนำฉันเพราะมือถือมาพร้อมกับ 3GB RAM และแท็บมาพร้อมกับ RAM 1.5GB ดังนั้นแท็บเล็ตจึงใช้ RAM ขนาดใหญ่เพราะหน้าจอขนาดใหญ่?
ราหุลมันดาลิยา

@RahulMandaliya: ฉันขอโทษ แต่ฉันไม่เข้าใจความกังวลของคุณหรือสิ่งที่เกี่ยวข้องกับคำถามนี้ คุณอาจต้องการเปิดคำถามสแต็คโอเวอร์โฟลว์แยกต่างหากซึ่งคุณจะอธิบายโดยละเอียดว่าอะไรคือสิ่งที่คุณกังวล
CommonsWare

15

มันเป็นจุดสิ้นสุดของปี 2018 ดังนั้นสิ่งต่างๆจึงเปลี่ยนไป

ก่อนอื่น: เปิดแอปของคุณและเปิดแท็บ Android Profiler ใน Android Studio คุณจะเห็นจำนวนหน่วยความจำที่ใช้ไปคุณจะประหลาดใจ แต่สามารถจัดสรร RAM ได้จำนวนมาก

นอกจากนี้ที่นี่เป็นบทความที่ยอดเยี่ยมในเอกสารอย่างเป็นทางการพร้อมคำแนะนำโดยละเอียดเกี่ยวกับวิธีการใช้ Memory Profiler ซึ่งสามารถให้การจัดการหน่วยความจำของคุณในเชิงลึก

แต่ในกรณีส่วนใหญ่ Android Profiler ปกติของคุณจะเพียงพอสำหรับคุณ

ป้อนคำอธิบายรูปภาพที่นี่

โดยปกติแล้วแอปจะเริ่มต้นด้วยการจัดสรร RAM ขนาด 50Mb แต่จะกระโดดได้สูงถึง 90Mb ทันทีเมื่อคุณเริ่มโหลดรูปภาพในหน่วยความจำ เมื่อคุณเปิดกิจกรรมด้วย ViewPager พร้อมภาพถ่ายที่โหลดไว้ล่วงหน้า (3,5Mb แต่ละรายการ) คุณสามารถรับ 190Mb ได้อย่างง่ายดายในไม่กี่วินาที

แต่นี่ไม่ได้หมายความว่าคุณมีปัญหากับการจัดการหน่วยความจำ

คำแนะนำที่ดีที่สุดที่ฉันสามารถให้ได้ก็คือปฏิบัติตามแนวทางและแนวปฏิบัติที่ดีที่สุดใช้ไลบรารี่ชั้นนำสำหรับการโหลดรูปภาพ (Glide, Picasso) และคุณจะโอเค


แต่ถ้าคุณต้องการปรับแต่งบางสิ่งและคุณจำเป็นต้องรู้จำนวนหน่วยความจำที่คุณสามารถจัดสรรได้ด้วยตนเองคุณจะได้รับหน่วยความจำฟรีทั้งหมดและคำนวณสัดส่วนที่กำหนดไว้ล่วงหน้า (เป็น%) ในกรณีของฉันฉันต้องแคชรูปถ่ายที่ถอดรหัสในหน่วยความจำดังนั้นฉันไม่จำเป็นต้องถอดรหัสพวกเขาทุกครั้งที่ผู้ใช้เลื่อนผ่านรายการ

เพื่อจุดประสงค์นี้คุณสามารถใช้พร้อมที่จะใช้ระดับ LruCache เป็นคลาสแคชที่ติดตามจำนวนหน่วยความจำที่ออบเจ็กต์ของคุณจัดสรร (หรือจำนวนอินสแตนซ์) โดยอัตโนมัติและลบสิ่งที่เก่าที่สุดเพื่อเก็บข้อมูลล่าสุดตามประวัติการใช้งาน นี่คือการสอนที่ดีเกี่ยวกับวิธีการใช้งาน

ในกรณีของฉันฉันสร้างแคช 2 อินสแตนซ์: สำหรับนิ้วหัวแม่มือและไฟล์แนบ ทำให้พวกเขาคงที่ด้วยการเข้าถึงซิงเกิลเพื่อให้พวกเขาทั่วโลกตลอดทั้งแอพ

คลาสแคช:

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 หรือแฮ็กอื่น ๆ ที่จะได้รับจำนวนหน่วยความจำที่จัดสรรให้แอปของคุณมันคำนวณได้ทันทีจากปัจจัยหลายประการ


PS ฉันใช้ฟิลด์คลาสคงที่เพื่อเก็บแคช แต่ตามแนวทาง Android ล่าสุดแนะนำให้ใช้ส่วนประกอบสถาปัตยกรรม ViewModelสำหรับจุดประสงค์นั้น


12

ขีด จำกัด หน่วยความจำต่อแอปขึ้นอยู่กับขนาดหน้าจอและรุ่น Android: https://drive.google.com/file/d/0B7Vx1OvzrLa3Y0R0X1BZbUpicGc/view?usp=sharing

แหล่งที่มา: ดาวน์โหลดความเข้ากันได้ของ Android http://source.android.com/compatibility/downloads.html ; เอกสารนิยามความเข้ากันได้ (CDD), ความเข้ากันได้ของเครื่องเสมือนหรือความเข้ากันได้ของรันไทม์ส่วน


2
URL ไดรฟ์ขอสิทธิ์การเข้าถึง
silent_grave
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.