งบประมาณหน่วยความจำสูงสุดของแอป ios


152

ฉันกำลังทำงานกับเกม iOS ที่กำหนดเป้าหมายเป็นอย่างน้อย 3gs เรากำลังใช้ทรัพย์สิน HD สำหรับอุปกรณ์แสดงผลเรตินา (iphone 4, ipod touch 4th gen)

หน่วยความจำที่ชาญฉลาด Ipod Touch 4th gen ดูเหมือนจะเป็นอุปกรณ์ที่ จำกัด ที่สุดสำหรับเราเนื่องจากมี RAM เท่ากัน (256 เทียบกับ Iphone 4 ของ 512) เป็น 3gs แต่เราใช้เนื้อหา HD ในนั้น แอปเคยขัดข้องเมื่อพยายามโหลด ram 100-110mb แต่ตอนนี้เราลดลงเหลือ 70MB แล้วเราไม่เคยโหลดขัดข้องเลย

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



14
ไม่แน่ใจว่าคำถามนี้จะซ้ำกับสิ่งที่ถามไว้ในเวลาต่อมาได้อย่างไร
Jasper

คำตอบ:


42

ฉันคิดว่าคุณตอบคำถามของคุณเอง: พยายามไม่ให้เกินขีด จำกัด 70 Mb แต่ขึ้นอยู่กับหลายสิ่ง: รุ่น iOS ที่คุณใช้ (ไม่ใช่ SDK) จำนวนแอปพลิเคชันที่ทำงานในพื้นหลังหน่วยความจำที่แน่นอน คุณกำลังใช้ ฯลฯ

เพียงหลีกเลี่ยงการกระเด็นของหน่วยความจำทันที (เช่นคุณใช้ RAM 40 Mb แล้วจัดสรรอีก 80 Mb เพื่อการคำนวณสั้น ๆ ) ในกรณีนี้ iOS จะฆ่าแอปพลิเคชันของคุณทันที

คุณควรพิจารณาการโหลดสินทรัพย์ที่สันหลังยาว (โหลดเมื่อคุณต้องการเท่านั้นและไม่ได้เตรียมไว้ล่วงหน้า)


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

2
จะจัดสรรเพียง 70MB (ซึ่งน่าจะอยู่ภายใต้งบประมาณ) ได้ตลอดเวลาบนอุปกรณ์นั้น (แม้หลังจากการใช้งานหนักในแอปที่ใช้หน่วยความจำอื่น ๆ ) จะรับประกันการจัดสรรที่ประสบความสำเร็จหรือไม่
Steven Lu

1
@Steven Lu มันขึ้นอยู่กับอุปกรณ์ของคุณ เช่นในรุ่นที่ใหม่กว่าเช่นการจัดสรร iPhone5 หรือ iPad4 70 Mb ไม่ใช่ปัญหาเลย
สูงสุด

1
ใช่ แต่ฉันต้องการทราบว่าฉันมั่นใจได้หรือไม่ว่าตราบใดที่ฉันยังคงใช้งานแอพของฉันทั้งหมดภายใต้งบประมาณหน่วยความจำเฉพาะของอุปกรณ์เวทมนต์มันจะไม่ถูกยกเลิก!
Steven Lu

1
ไม่มีการรับประกัน
สูงสุด

421

ผลลัพธ์ของการทดสอบด้วยยูทิลิตี้แยกเขียน (ลิงก์อยู่ในคำตอบของเขา):

อุปกรณ์: (จำนวนความผิดพลาด / ยอดรวม / ร้อยละของทั้งหมด)

  • iPad1: 127MB / 256MB / 49%
  • iPad2: 275MB / 512MB / 53%
  • iPad3: 645MB / 1024MB / 62%
  • iPad4: 585MB / 1024MB / 57% (iOS 8.1)
  • iPad Mini เจนเนอเรชั่นที่ 297MB / 512MB / 58%
  • iPad Mini retina: 696MB / 1024MB / 68% (iOS 7.1)
  • iPad Air: 697MB / 1024MB / 68%
  • iPad Air 2: 1383MB / 2048MB / 68% (iOS 10.2.1)
  • iPad Pro 9.7 ": 1395MB / 1971MB / 71% (iOS 10.0.2 (14A456))
  • iPad Pro 10.5”: 3057/4000/76% (iOS 11 เบต้า 4)
  • iPad Pro 12.9” (2015): 3058/3999/76% (iOS 11.2.1)
  • iPad Pro 12.9” (2017): 3057/3974/77% (iOS 11 เบต้า 4)
  • iPad Pro 11.0” (2018): 2858/3769/76% (iOS 12.1)
  • iPad Pro 12.9” (2018, 1TB): 4598/5650/81% (iOS 12.1)
  • iPad 10.2: 1844/2998/62% (iOS 13.2.3)
  • iPod touch รุ่นที่ 4: 130MB / 256MB / 51% (iOS 6.1.1)
  • iPod touch รุ่นที่ 5: 286MB / 512MB / 56% (iOS 7.0)
  • iPhone4: 325MB / 512MB / 63%
  • iPhone4s: 286MB / 512MB / 56%
  • iPhone5: 645MB / 1024MB / 62%
  • iPhone5s: 646MB / 1024MB / 63%
  • iPhone6: 645MB / 1024MB / 62% (iOS 8.x)
  • iPhone6 ​​+: 645MB / 1024MB / 62% (iOS 8.x)
  • iPhone6 ​​s: 1396MB / 2048MB / 68% (iOS 9.2)
  • iPhone6 ​​s +: 1392MB / 2048MB / 68% (iOS 10.2.1)
  • iPhoneSE: 1395MB / 2048MB / 69% (iOS 9.3)
  • iPhone7: 1395 / 2048MB / 68% (iOS 10.2)
  • iPhone7 +: 2040MB / 3072MB / 66% (iOS 10.2.1)
  • iPhone8: 1364 / 1990MB / 70% (iOS 12.1)
  • iPhone X: 1392/2785/50% (iOS 11.2.1)
  • iPhone XS: 2040/3754/54% (iOS 12.1)
  • iPhone XS Max: 2039/3735/55% (iOS 12.1)
  • iPhone XR: 1792/2813/63% (iOS 12.1)
  • iPhone 11: 2068/3844/54% (iOS 13.1.3)
  • iPhone 11 Pro สูงสุด: 2067/3740/55% (iOS 13.2.3)

2
iPhone4: ยืนยันค่าที่คล้ายกันดูเหมือนว่าถูกต้อง: P
cprcrack

3
iPhone 5 ล่มที่± 645 MB
asp_net

4
@JasperPol ฉันได้แก้ไขโพสต์ของคุณเพื่อรวมอุปกรณ์ต่าง ๆ ที่ฉันมีฉันหวังว่าไม่เป็นไร ฉันได้เพิ่มเวอร์ชัน iOS ที่ฉันทดสอบในกรณีที่สำคัญ แต่โปรดลบออกหากคุณคิดว่ามันไม่สำคัญ
JosephH

2
ยอดเยี่ยมที่รายการนี้ถูกสร้างและดูแล จากประสบการณ์ของฉันฉันต้องเก็บความทรงจำที่ต่ำกว่าเพื่อความปลอดภัยบางทีอาจเป็น 20% ของสิ่งที่ปรากฏที่นี่ ความแตกต่างระหว่างอุปกรณ์กับอุปกรณ์ก็มีความผันแปรสูงเช่นกัน
user1021430

1
เพียงแค่ใช้งานบน 12.9 iPad Pro คำเตือนหน่วยความจำที่ 2451MB เกิดข้อผิดพลาดที่ 3064MB รวม 3981MB
ล็อค

134

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

https://github.com/Split82/iOSMemoryBudgetTest


ฉันทำการทดสอบที่น่าสนใจ: เรียกใช้แอปของฉันด้วยการใช้หน่วยความจำการตรวจสอบ xcode, ป้อนพื้นหลัง, เรียกใช้ BudgetTest การทดสอบถูกฆ่าขณะที่แอปในพื้นหลังของฉันไม่ได้ ฉันสนใจที่จะรู้ว่าทำไม นอกจากนี้สิ่งนี้ยังขัดแย้งกับสิ่งที่ @cprcrack พูดในคำตอบอื่น ๆ
Roberto

19

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

ในกรณีที่มีคนต้องการดูการใช้งานจริงของฉัน:

#import "mach/mach.h"

- (void)didReceiveMemoryWarning
{
    // Remember to call super
    [super didReceiveMemoryWarning];

    // If we are using more than 45% of the memory, free even important resources,
    // because the app might be killed by the OS if we don't
    if ([self __getMemoryUsedPer1] > 0.45)
    {
        // Free important resources here
    }

    // Free regular unimportant resources always here
}

- (float)__getMemoryUsedPer1
{
    struct mach_task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size);
    if (kerr == KERN_SUCCESS)
    {
        float used_bytes = info.resident_size;
        float total_bytes = [NSProcessInfo processInfo].physicalMemory;
        //NSLog(@"Used: %f MB out of %f MB (%f%%)", used_bytes / 1024.0f / 1024.0f, total_bytes / 1024.0f / 1024.0f, used_bytes * 100.0f / total_bytes);
        return used_bytes / total_bytes;
    }
    return 1;
}

Swift (ตามคำตอบนี้ ):

func __getMemoryUsedPer1() -> Float
{
    let MACH_TASK_BASIC_INFO_COUNT = (sizeof(mach_task_basic_info_data_t) / sizeof(natural_t))
    let name = mach_task_self_
    let flavor = task_flavor_t(MACH_TASK_BASIC_INFO)
    var size = mach_msg_type_number_t(MACH_TASK_BASIC_INFO_COUNT)
    var infoPointer = UnsafeMutablePointer<mach_task_basic_info>.alloc(1)
    let kerr = task_info(name, flavor, UnsafeMutablePointer(infoPointer), &size)
    let info = infoPointer.move()
    infoPointer.dealloc(1)
    if kerr == KERN_SUCCESS
    {
        var used_bytes: Float = Float(info.resident_size)
        var total_bytes: Float = Float(NSProcessInfo.processInfo().physicalMemory)
        println("Used: \(used_bytes / 1024.0 / 1024.0) MB out of \(total_bytes / 1024.0 / 1024.0) MB (\(used_bytes * 100.0 / total_bytes)%%)")
        return used_bytes / total_bytes
    }
    return 1
}

1
ขนาดควรเป็น TASK_BASIC_INFO_COUNT แทนที่จะเป็น sizeof (ข้อมูล) - ความผิดพลาดนี้ถูกคัดลอกไปยังหลายสถานที่ด้วยรหัสเดียวกัน
Maxim Kholyavkin

ขอบคุณ Speakus คุณดูเหมือนถูกต้องตามลิงค์นี้ คุณมีข้อมูลอ้างอิงอื่น ๆ ที่สามารถพบข้อมูลนี้ได้หรือไม่?
cprcrack

แอปเปิ้ลใช้ TASK_BASIC_INFO_COUNT เช่นกัน
Maxim Kholyavkin

45% ไม่ได้เป็นข้อ จำกัด ที่ปลอดภัยอีกต่อไปมันใกล้เคียงกับค่าความผิดพลาด 50% สำหรับ iPhone X ผมขอแนะนำให้ใช้ 40% หรือแยกค่าสำหรับแต่ละอุปกรณ์
Slyv

8

เมื่อทำการแยก SPLITS repo ฉันได้สร้างหน่วยความจำเพื่อทดสอบหน่วยความจำ iOS ที่สามารถจัดสรรให้กับส่วนขยายของวันนี้

iOSMemoryBudgetTestForExtension

ต่อไปนี้เป็นผลลัพธ์ที่ฉันได้รับใน iPhone 5s

เตือนหน่วยความจำที่ 10 MB

แอปขัดข้องที่ 12 MB

โดยวิธีการนี้แอปเปิ้ลเป็นเพียงการช่วยให้ส่วนขยายใด ๆ ที่จะทำงานร่วมกับศักยภาพของพวกเขา


7

คุณควรจะดูเซสชั่น 147 จากWWDC 2010 วิดีโอเซสชัน มันคือ "การเพิ่มประสิทธิภาพขั้นสูงใน iPhone OS ตอนที่ 2"
มีคำแนะนำที่ดีมากมายเกี่ยวกับการเพิ่มประสิทธิภาพหน่วยความจำ

เคล็ดลับบางประการคือ:

  • ใช้NSAutoReleasePools ที่ซ้อนกันเพื่อให้แน่ใจว่าการใช้หน่วยความจำของคุณไม่ขัดขวาง
  • ใช้CGImageSourceเมื่อสร้างภาพขนาดย่อจากภาพขนาดใหญ่
  • ตอบสนองต่อการเตือนหน่วยความจำเหลือน้อย

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

ตกลง. ข้อผิดพลาดจะเกิดขึ้นเนื่องจากระบบปฏิบัติการกำลังยกเลิกแอปเนื่องจากหน่วยความจำที่ จำกัด คุณสามารถเพิ่มNSLogข้างในdidReceiveMemoryWarningแล้วทำการทดสอบที่คุณจัดสรรหน่วยความจำในจำนวนที่แตกต่างกันแล้วดูว่าเมื่อคำเตือนหน่วยความจำเริ่มที่จะเตะ
Kobski

4

เริ่มต้นด้วย iOS13 มีวิธีสอบถามจาก Apple ที่สนับสนุนโดยใช้วิธีนี้

#include <os/proc.h>

size_t os_proc_available_memory(void)

แนะนำที่นี่: https://developer.apple.com/videos/play/wwdc2019/606/

รอบขั้นต่ำ 29-ish

แก้ไข: การเพิ่มลิงก์ไปยังเอกสาร https://developer.apple.com/documentation/os/3191911-os_proc_available_memory?language=objc


ที่สุด! ฉันทดสอบ os_proc_available_memory () ในอุปกรณ์ไม่กี่เครื่องและผลลัพธ์คล้ายกับค่าที่ฉันเป็นตารางใหญ่ด้านบน!
Slyv

3
- (float)__getMemoryUsedPer1
{
    struct mach_task_basic_info info;
    mach_msg_type_number_t size = MACH_TASK_BASIC_INFO;
    kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size);
    if (kerr == KERN_SUCCESS)
    {
        float used_bytes = info.resident_size;
        float total_bytes = [NSProcessInfo processInfo].physicalMemory;
        //NSLog(@"Used: %f MB out of %f MB (%f%%)", used_bytes / 1024.0f / 1024.0f, total_bytes / 1024.0f / 1024.0f, used_bytes * 100.0f / total_bytes);
        return used_bytes / total_bytes;
    }
    return 1;
}

หากใครจะใช้ TASK_BASIC_INFO_COUNT แทน MACH_TASK_BASIC_INFO คุณจะได้รับ

kerr == KERN_INVALID_ARGUMENT (4)


อย่างน้อยคุณควรพูดถึงว่าคำตอบของคุณเกือบเป็นสำเนา & paste ของ@ cprcrackด้านบน ข้อแตกต่างเพียงอย่างเดียวคือ TASK_BASIC_INFO_COUNT
mrvincenzo

2

ฉันสร้างรายการอีกหนึ่งรายการโดยเรียงลำดับรายการ Jaspers ตาม RAM ของอุปกรณ์ (ฉันทำการทดสอบด้วยเครื่องมือของ Split และแก้ไขผลลัพธ์บางอย่าง - ตรวจสอบความคิดเห็นของฉันในเธรด Jaspers)

RAM อุปกรณ์: ช่วงเปอร์เซ็นต์ที่จะผิดพลาด

  • 256MB: 49% - 51%
  • 512MB: 53% - 63%
  • 1024MB: 57% - 68%
  • 2048MB: 68% - 69%
  • 3072MB: 63% - 66%
  • 4096MB: 77%
  • 6144MB: 81%

กรณีพิเศษ:

  • iPhone X (3072MB): 50%
  • iPhone XS / XS สูงสุด (4096MB): 55%
  • iPhone XR (3072MB): 63%
  • iPhone 11/11 Pro Max (4096MB): 54% - 55%

Device RAM สามารถอ่านได้ง่าย:

[NSProcessInfo processInfo].physicalMemory

จากประสบการณ์ของฉันมันปลอดภัยที่จะใช้ 45% สำหรับอุปกรณ์ 1GB, 50% สำหรับอุปกรณ์ 2 / 3GB และ 55% สำหรับอุปกรณ์ 4GB เปอร์เซ็นต์สำหรับ macOS อาจใหญ่กว่านี้เล็กน้อย


อัปเดต: ดูเหมือนว่า iPhone X เป็นข้อยกเว้น - มันล้มเหลวเมื่อใช้ RAM 50% (ทดสอบด้วยแอป iOSMemoryBudgetTest) ฉันอัปเดตรายการ
Slyv

0

จากการทำงานกับคำตอบมากมายข้างต้นฉันได้ติดตั้งแอปเปิ้ลวิธีการใหม่os_proc_available_memory()สำหรับ iOS 13+ ควบคู่ไปกับการNSByteCountFormatterเสนอตัวเลือกการจัดรูปแบบที่มีประโยชน์มากมายสำหรับหน่วยความจำ nicer output:

#include <os/proc.h>

....

- (NSString *)memoryStringForBytes:(unsigned long long)memoryBytes {
    NSByteCountFormatter *byteFormatter = [[NSByteCountFormatter alloc] init];
    byteFormatter.allowedUnits = NSByteCountFormatterUseGB;
    byteFormatter.countStyle = NSByteCountFormatterCountStyleMemory;
    NSString *memoryString = [byteFormatter stringFromByteCount:memoryBytes];
    return memoryString;
}

- (void)memoryLoggingOutput {
    if (@available(iOS 13.0, *)) {
        NSLog(@"Physical memory available: %@", [self memoryStringForBytes:[NSProcessInfo processInfo].physicalMemory]);
        NSLog(@"Memory A (brackets): %@", [self memoryStringForBytes:(long)os_proc_available_memory()]);
        NSLog(@"Memory B (no brackets): %@", [self memoryStringForBytes:(long)os_proc_available_memory]);
    }
}

หมายเหตุสำคัญ: อย่าลืม()ตอนจบ ฉันได้รวมทั้งNSLogตัวเลือกไว้ในmemoryLoggingOutputวิธีการเพราะมันไม่ได้เตือนคุณว่าพวกเขาจะหายไปและความล้มเหลวในการรวมวงเล็บจะส่งกลับผลลัพธ์ที่ไม่คาดคิด แต่คงที่

สตริงที่ส่งคืนจากเมธอดจะmemoryStringForBytesแสดงค่าดังนี้:

NSLog(@"%@", [self memoryStringForBytes:(long)os_proc_available_memory()]); // 1.93 GB
// 2 seconds later
NSLog(@"%@", [self memoryStringForBytes:(long)os_proc_available_memory()]); // 1.84 GB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.