ios ऐप अधिकतम मेमोरी बजट


152

मैं एक ios गेम पर काम कर रहा हूं जो न्यूनतम 3gs के रूप में लक्षित है। हम रेटिना डिस्प्ले डिवाइस (iphone 4, ipod टच 4th gen) के लिए HD एसेट्स का उपयोग कर रहे हैं।

मेमोरी के लिहाज से, आईपोड टच 4 जी जीन हमारे लिए सबसे अधिक अवरोधक उपकरण लगता है क्योंकि इसमें 3 ग्राम के समान रैम (256 Iphone 4 के 512 की तुलना में) की मात्रा है, लेकिन हम इस पर एचडी संपत्ति का उपयोग कर रहे हैं। जब ऐप 100-110mb की रैम लोड करने की कोशिश कर रहा था तो क्रैश हो गया था लेकिन अब जब हम 70MB से नीचे हैं, तो हमारे पास लोडिंग क्रैश कभी नहीं था।

चारों ओर बहुत खोज करने के बाद, कोई आधिकारिक कठिन सीमा नहीं है, इसलिए हमें यह जानना चाहिए कि सुरक्षित होने के लिए किस मेमोरी बजट का उपयोग करना चाहिए? हम कलाकारों को एक बजट देने में सक्षम होना चाहते हैं जिसे वे प्रत्येक नक्शे के लिए मेमोरी चिंताओं के बिना उपयोग कर सकते हैं।



14
निश्चित नहीं कि यह प्रश्न किसी चीज़ का दोहराव कैसे हो सकता है जो बाद के समय में पूछा गया था।
जैस्पर

जवाबों:


42

मुझे लगता है कि आपने अपने स्वयं के प्रश्न का उत्तर दिया है: 70 एमबी की सीमा से आगे नहीं जाने का प्रयास करें, हालांकि यह वास्तव में कई चीजों पर निर्भर करता है: आप किस iOS संस्करण का उपयोग कर रहे हैं (एसडीके नहीं), पृष्ठभूमि में कितने अनुप्रयोग चल रहे हैं, क्या सटीक मेमोरी आप उपयोग कर रहे हैं आदि।

बस तुरंत मेमोरी स्पलैश से बचें (जैसे कि आप 40 एमबी रैम का उपयोग कर रहे हैं, और फिर कुछ कम गणना के लिए 80 एमबी के अधिक आवंटित कर रहे हैं)। इस मामले में iOS आपके आवेदन को तुरंत मार देगा।

आपको परिसंपत्तियों के आलसी लोडिंग पर भी विचार करना चाहिए (केवल उन्हें लोड करें जब आपको वास्तव में ज़रूरत हो और पहले से नहीं)।


2
यह सिर्फ इतना है कि हम उतना ही सामान रखना चाहते थे जितना हम (ग्राफिक्स और लगता है)। कलाकार हमेशा उतना ही रखना चाहेंगे जितना वे संभवतः एक खेल में लगा सकते हैं इसलिए मैं उन्हें एक बजट के साथ सीमित करना चाहता हूं। मुझे लगता है कि हमें उपयोग करने के लिए एक उचित अधिकतम मेमोरी फ़ुटप्रिंट खोजने के लिए विभिन्न सेटिंग्स में कई अलग-अलग डिवाइसों पर परीक्षण करना होगा।
फिला

2
उस डिवाइस पर किसी भी समय केवल 70 एमबी (जो कि बजट के तहत संभव है) आवंटित कर रहा है (यहां तक ​​कि अन्य मेमोरी-भूखे ऐप्स में भारी उपयोग के बाद) हमेशा एक सफल आवंटन की गारंटी देता है, या क्या यह संभावित रूप से दुर्घटनाग्रस्त हो जाएगा?
स्टीवन लू

1
@ सेंट लु यह आपके डिवाइस पर निर्भर करता है। जैसे iPhone5 या iPad4 70 एमबी के आवंटन पर नए लोगों को कोई समस्या नहीं है।
अधिकतम

1
हां, लेकिन मैं यह जानना चाहता हूं कि क्या मैं यह सुनिश्चित कर सकता हूं कि जब तक मैं अपने ऐप के कुल उपयोग को जादुई डिवाइस के विशिष्ट मेमोरी बजट के तहत रखता हूं कि यह समाप्त नहीं होगा!
स्टीवन लू

1
कोई गारंटी नहीं है
मैक्स

421

स्प्लिट उपयोगिता के साथ परीक्षण के परिणाम लिखे (लिंक उनके उत्तर में है):

डिवाइस: (दुर्घटना राशि / कुल राशि / कुल प्रतिशत)

  • iPad1: 127MB / 256MB / 49%
  • iPad2: 275MB / 512MB / 53%
  • iPad3: 645MB / 1024MB / 62%
  • iPad4: 585MB / 1024MB / 57% (iOS 8.1)
  • iPad मिनी पहली पीढ़ी: 297MB / 512MB / 58%
  • iPad मिनी रेटिना: 696MB / 1024MB / 68% (iOS 7.1)
  • iPad वायु: 697MB / 1024MB / 68%
  • iPad एयर 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 beta4)
  • iPad Pro 12.9 ”(2015): 3058/3999/76% (iOS 11.2.1)
  • iPad Pro 12.9 ”(2017): 3057/3974/77% (iOS 11 beta4)
  • 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)
  • आइपॉड टच 4 जी जीन: 130 एमबी / 256 एमबी / 51% (आईओएस 6.1.1)
  • iPod टच 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)
  • iPhone6s: 1396MB / 2048MB / 68% (iOS 9.2)
  • iPhone6s +: 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 मैक्स: 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 प्रो मैक्स: 2067/3740/55% (iOS 13.2.3)

2
iPhone4: इसी तरह की कीमत की पुष्टि की, कानूनी लगता है: P
cprcrack

3
iPhone 5 45 645 MB पर क्रैश हो जाता है।
asp_net

4
@JasperPol मैंने आपके पोस्ट को विभिन्न उपकरणों में शामिल करने के लिए संपादित किया है, मुझे आशा है कि यह ठीक है। मैंने iOS संस्करण जोड़ा है जो मैंने मामले में परीक्षण किया है, लेकिन यह महत्वपूर्ण है यदि आपको लगता है कि यह महत्वपूर्ण नहीं है तो इसे हटाने के लिए स्वतंत्र महसूस करें।
जोसेफ

2
बहुत बढ़िया है कि यह सूची बनाई और बनाए रखी गई है। अपने अनुभव में, मुझे स्मृति को सुरक्षित रखने के लिए बहुत कम रखना है, हो सकता है कि यहां दिखाया गया 20% हो। डिवाइस-टू-डिवाइस अंतर भी अत्यधिक परिवर्तनशील हैं।
user1021430

1
बस इसे 12.9 iPad प्रो पर चलाया गया। 2451MB पर मेमोरी चेतावनी, 3064MB पर क्रैश, कुल 3981MB।
लॉक करें

134

मैंने छोटी उपयोगिता बनाई जो क्रैश करने के लिए जितनी संभव हो उतनी मेमोरी आवंटित करने की कोशिश करता है और यह रिकॉर्ड करता है जब मेमोरी चेतावनियां और क्रैश हुआ। यह पता लगाने में मदद करता है कि किसी भी आईओएस डिवाइस के लिए मेमोरी बजट क्या है।

https://github.com/Split82/iOSMemoryBudgetTest


मैंने एक दिलचस्प परीक्षण किया: अपने ऐप को एक्सकोड मॉनिटरिंग मेमोरी उपयोग के साथ चलाया, पृष्ठभूमि में प्रवेश किया, बजटटेस्ट चलाया। जब मेरा इन-बैकग्राउंड ऐप नहीं था, तब टेस्ट मारा गया। मुझे यह जानने में दिलचस्पी है कि क्यों। इसके अलावा, यह दूसरे उत्तर में @cprcrack ने जो कहा उसके खिलाफ जाता है।
रॉबर्टो

19

मेरे ऐप में, उपयोगकर्ता अनुभव बेहतर है यदि अधिक मेमोरी का उपयोग किया जाता है, तो मुझे यह तय करना होगा कि क्या मुझे वास्तव में सभी मेमोरी को मुफ्त करना चाहिए जो मैं अंदर कर सकता हूंdidReceiveMemoryWarning । स्प्लिट्स और जैस्पर पोल के जवाब के आधार पर, कुल डिवाइस मेमोरी का अधिकतम 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;
}

स्विफ्ट ( इस उत्तर पर आधारित ):

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 होना चाहिए - यह गलती समान कोड वाली कई जगहों पर कॉपी-पेस्ट की गई
Maxim Kholyavkin

धन्यवाद स्पीकस आप इस लिंक के आधार पर सही प्रतीत हो रहे हैं । क्या आपके पास कोई अन्य संदर्भ है जहां यह जानकारी मिल सकती है?
cccrack

सेब TASK_BASIC_INFO_COUNT का भी
Maxim Kholyavkin

45% अब सुरक्षित सीमा नहीं है, यह iPhone X के लिए 50% क्रैश मान के करीब है। मेरा सुझाव है कि प्रत्येक डिवाइस के लिए 40% या अलग मूल्य का उपयोग करें।
स्लीव

8

SPLITS रेपो फोर्क करके, मैंने iOS मेमोरी को टेस्ट करने के लिए एक बनाया है जिसे आज के एक्सटेंशन में आवंटित किया जा सकता है

iOSMemoryBudgetTestForExtension

निम्नलिखित परिणाम है कि मैं iPhone 5s में मिला है

10 एमबी पर मेमोरी वार्निंग

12 एमबी पर ऐप क्रैश

इस तरह से Apple केवल किसी भी एक्सटेंशन को अपनी पूरी क्षमता के साथ काम करने की अनुमति दे रहा है


7

आपको WWDC 2010 सत्र वीडियो से सत्र 147 देखना चाहिए । यह "iPhone OS पर उन्नत प्रदर्शन अनुकूलन, भाग 2" है।
मेमोरी ऑप्टिमाइजेशन पर बहुत अच्छी सलाह है।

सुझावों में से कुछ हैं:

  • NSAutoReleasePoolयह सुनिश्चित करने के लिए नेस्टेड एस का उपयोग करें कि आपकी मेमोरी का उपयोग स्पाइक नहीं करता है।
  • उपयोग CGImageSourceबड़ी छवियों से थंबनेल बनाते समय ।
  • कम स्मृति चेतावनी का जवाब दें।

मेरा प्रश्न यह नहीं है कि अनुकूलन कैसे करें (हालांकि लिंक के लिए धन्यवाद), यह इस बारे में है कि हम अपने आप को उपयोग करने की कितनी अनुमति दे सकते हैं। इसका कारण यह है कि उदाहरण के लिए, यदि हम 20mb प्राप्त करने के लिए अनुकूलन करते हैं, तो कलाकार उस 20mb का उपयोग करना चाहेंगे यदि यह उचित "बजट" के भीतर है, तो यह सुनिश्चित करें कि यह किसी भी प्रदर्शन के मुद्दों या मेमोरी क्रैश का कारण नहीं होगा।
फिला

ठीक है। क्रैश इसलिए होगा क्योंकि ओएस विवश मेमोरी के कारण ऐप को समाप्त कर रहा है। आप बस एक NSLogअंदर जोड़ सकते हैं didReceiveMemoryWarningऔर फिर कुछ परीक्षण कर सकते हैं जहां आप अलग-अलग मात्रा में मेमोरी आवंटित करते हैं और फिर देखते हैं कि मेमोरी कब किक करने के लिए चेतावनी देती है।
कोब्स्की

4

IOS13 के साथ शुरू, इसका उपयोग करके Apple-समर्थित तरीका है

#include <os/proc.h>

size_t os_proc_available_memory(void)

यहां प्रस्तुत है: https://developer.apple.com/videos/play/wwdc2019/606/

लगभग 29-ईश।

संपादित करें: दस्तावेज़ में लिंक जोड़ना https://developer.apple.com/documentation/os/3191911-os_proc_available_memory?language=objc


आखिरकार! मैंने कुछ उपकरणों पर os_proc_available_memory () का परीक्षण किया, और परिणाम ऊपर की बड़ी तालिका के मानों के समान हैं!
स्लीव

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;
}

यदि कोई MACH_TASK_BASIC_INFO के बजाय TASK_BASIC_INFO_COUNT का उपयोग करेगा, तो आपको मिलेगा

केर == KERN_INVALID_ARGUMENT (4)


आपको कम से कम उल्लेख करना चाहिए कि आपका उत्तर @ cprcrack के ऊपर की एक सटीक प्रतिलिपि और पेस्ट है । एकमात्र अंतर TASK_BASIC_INFO_COUNT है।
mrvincenzo

2

मैंने डिवाइस रैम द्वारा जसपर्स सूची को क्रमबद्ध करके एक और सूची बनाई (मैंने स्प्लिट्स टूल के साथ अपने स्वयं के परीक्षण किए और कुछ परिणाम तय किए - जसपर्स थ्रेड में मेरी टिप्पणियों की जांच करें)।

डिवाइस रैम: क्रैश करने के लिए प्रतिशत सीमा

  • 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 प्रो मैक्स (4096MB): 54% - 55%

डिवाइस रैम को आसानी से पढ़ा जा सकता है:

[NSProcessInfo processInfo].physicalMemory

मेरे अनुभव से 1GB डिवाइस के लिए 45%, 2 / 3GB डिवाइस के लिए 50% और 4GB डिवाइस के लिए 55% का उपयोग करना सुरक्षित है। MacOS के लिए प्रतिशत थोड़ा बड़ा हो सकता है।


अद्यतन: ऐसा लगता है कि iPhone X एक अपवाद है - यह तब क्रैश होता है जब 50% RAM का उपयोग किया जाता है (iOSMemoryBudgetTit ऐप के साथ परीक्षण किया गया)। मैंने सूची अपडेट की।
स्लीव

0

उपरोक्त कई उत्तरों के साथ काम करते हुए, मैंने os_proc_available_memory()iOS 13+ के लिए Apple की नई विधि लागू की है NSByteCountFormatterजिसके साथ युग्मित किया गया है जो मेमोरी के अच्छे आउटपुट के लिए कई उपयोगी स्वरूपण विकल्प प्रदान करता है:

#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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.