iOS 앱 최대 메모리 예산


152

최소 3gs를 목표로하는 iOS 게임을 만들고 있습니다. 우리는 레티 나 디스플레이 장치 (iphone 4, ipod touch 4 세대)에 HD 자산을 사용하고 있습니다.

메모리 측면에서 볼 때, Ipod Touch 4 세대는 3gs와 동일한 양의 RAM (256과 비교하여 256)을 갖기 때문에 우리에게 가장 제약적인 장치 인 것 같습니다. 그러나 HD 자산을 사용하고 있습니다. 100-110mb의 램을로드하려고 할 때 응용 프로그램이 충돌했지만 이제는 70MB로 줄어 들었으므로로드 충돌이 없었습니다.

주변을 많이 검색 한 후에는 공식적인 하드 제한이없는 것처럼 보이므로 안전을 위해 사용할 메모리 예산을 어떻게 알 수 있습니까? 아티스트가 각지도에 대한 메모리 걱정없이 사용할 수있는 예산을 제공 할 수 있기를 원합니다.



14
이 질문이 나중에 요청 된 내용과 어떻게 중복 될 수 있는지 잘 모르겠습니다.
재스퍼

답변:


42

나는 당신이 당신의 자신의 질문에 대답했다고 생각합니다 : 70 Mb 한도를 넘지 마십시오. 그러나 그것은 실제로 많은 것들에 달려 있습니다 : 당신이 사용하는 iOS 버전 (SDK가 아닌), 백그라운드에서 실행중인 응용 프로그램의 수, 정확한 메모리 당신은 등을 사용하고 있습니다

즉석 메모리 스플래쉬를 피하십시오 (예 : 40Mb의 RAM을 사용하고 약간의 짧은 계산을 위해 80Mb를 더 할당). 이 경우 iOS는 즉시 응용 프로그램을 종료합니다.

자산의 게으른 로딩도 고려해야합니다 (사전 필요하지 않은 경우에만로드).


2
우리가 할 수있는 것 (그래픽 및 사운드)을 최대한 많이 넣고 싶었을뿐입니다. 아티스트는 항상 가능한 한 많이 게임에 투자하기를 원하므로 예산으로 제한하고 싶습니다. 사용할 수있는 합당한 최대 메모리 공간을 찾기 위해 다른 설정의 여러 장치에서 테스트해야 할 것 같습니다.
frilla

2
해당 장치 에서 언제라도 70MB (예산이 부족할 것) 만 할당하면 ( 메모리가 부족한 다른 응용 프로그램을 많이 사용한 후에도) 항상 성공적인 할당을 보장합니까, 아니면 여전히 충돌이 발생합니까?
Steven Lu

1
@Steven Lu 기기에 따라 다릅니다. 예를 들어 iPhone5 또는 iPad4 70 Mb 할당과 같은 최신 버전에서는 전혀 문제가되지 않습니다.
Max

1
예,하지만 마법의 장치 별 메모리 예산으로 앱의 총 사용량을 유지하는 한 종료되지 않을 것이라고 확신 할 수 있는지 알고 싶습니다!
Steven Lu

1
보장은 없습니다
Max

421

Split이 쓴 유틸리티를 사용한 테스트 결과 (링크는 그의 답변입니다) :

기기 : (충돌 량 / 총량 / 총 백분율)

  • iPad1 : 127MB / 256MB / 49 %
  • iPad2 : 275MB / 512MB / 53 %
  • iPad3 : 645MB / 1024MB / 62 %
  • iPad4 : 585MB / 1024MB / 57 % (iOS 8.1)
  • iPad Mini 1 세대 : 297MB / 512MB / 58 %
  • iPad Mini 망막 : 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)
  • 아이폰 4 : 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)
  • 아이폰 8 : 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)
  • 아이폰 XR : 1792 / 2813 / 63 % (iOS 12.1)
  • 아이폰 11 : 2068 / 3844 / 54 % (iOS 13.1.3)
  • iPhone 11 Pro Max : 2067 / 3740 / 55 % (iOS 13.2.3)

2
iPhone4 : 비슷한 가치 확인, 합법적 인 것 같다 : P
cprcrack

3
iPhone 5는 ± 645MB에서 충돌합니다.
asp_net

4
@JasperPol 다양한 기기를 포함하도록 게시물을 수정했습니다. 괜찮습니다. 중요한 경우 테스트 한 iOS 버전을 추가했지만 중요하지 않다고 생각되면 자유롭게 제거하십시오.
JosephH

2
이 목록이 만들어지고 유지되었습니다. 내 경험상, 안전을 위해 메모리를 훨씬 더 낮게 유지해야했습니다. 여기에 표시된 것의 20 % 일 것입니다. 장치 간 차이도 매우 다양합니다.
user1021430 2009 년

1
12.9 iPad Pro에서 이것을 실행했습니다. 2451MB의 메모리 경고, 3064MB의 충돌, 총 3981MB.
잠금

134

나는 가능한 많은 메모리를 할당하려고 시도하는 작은 유틸리티를 만들었고 메모리 경고와 충돌이 발생했을 때 기록합니다. 이것은 iOS 기기의 메모리 예산을 찾는 데 도움이됩니다.

https://github.com/Split82/iOSMemoryBudgetTest


흥미로운 테스트를했습니다 : xcode 모니터링 메모리 사용으로 앱을 실행하고 백그라운드를 입력하고 BudgetTest를 실행했습니다. 백그라운드 앱이없는 동안 테스트가 종료되었습니다. 이유를 알고 싶습니다. 또한 이것은 다른 답변에서 @cprcrack이 말한 것과 반대입니다.
Roberto

19

내 응용 프로그램에서 더 많은 메모리를 사용하면 사용자 경험이 향상되므로 가능한 모든 메모리 를 확보 해야하는지 결정해야합니다 didReceiveMemoryWarning. Split과 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;
}

스위프트 ( 이 답변을 기반으로 함 ) :

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
크기는 sizeof (info) 대신 TASK_BASIC_INFO_COUNT 여야합니다.이 실수는 동일한 코드로 여러 곳에 복사하여 붙여 넣기
Maxim Kholyavkin

고마워요. 이 링크를 기반으로 올바른 것 같습니다 . 이 정보를 찾을 수있는 다른 참조 자료가 있습니까?
cprcrack

사과 TASK_BASIC_INFO_COUNT를 사용
맥심 Kholyavkin

45 %는 더 이상 안전 제한이 아니며 iPhone X의 충돌 값이 50 %에 너무 가깝습니다. 40 % 또는 각 장비마다 별도의 값을 사용하는 것이 좋습니다.
Slyv

8

SPLITS 저장소를 포크하여 오늘 확장에 할당 할 수있는 iOS 메모리를 테스트하기 위해 하나를 만들었습니다.

iOSMemoryBudgetTestForExtension

다음은 iPhone 5s에서 얻은 결과입니다.

10MB의 메모리 경고

12MB에서 앱이 다운 됨

즉, 애플은 확장 기능을 최대한 활용할 수 있도록 허용하고있다 .


7

WWDC 2010 세션 비디오 에서 세션 147을 시청해야 합니다 . "iPhone OS의 고급 성능 최적화, 2 부"입니다.
메모리 최적화에 대한 많은 좋은 조언이 있습니다.

팁 중 일부는 다음과 같습니다.

  • 중첩 사용 NSAutoReleasePool 하여 메모리 사용량이 급증하지 않도록하십시오.
  • CGImageSource큰 이미지에서 썸네일을 만들 때 사용하십시오 .
  • 메모리 부족 경고에 응답하십시오.

내 질문은 최적화하는 방법에 대한 것이 아니라 (링크 덕분에), 우리가 얼마나 많이 사용할 수 있는지에 관한 것입니다. 예를 들어, 20MB를 얻도록 최적화하면 아티스트가 합리적인 "예산"내에있는 경우 해당 20MB를 사용하여 성능 문제 나 메모리 충돌이 발생하지 않도록해야합니다.
frilla

확인. 제한된 메모리로 인해 OS가 앱을 종료하기 때문에 충돌이 발생합니다. 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;
}

MACH_TASK_BASIC_INFO 대신 TASK_BASIC_INFO_COUNT를 사용하면

커 == KERN_INVALID_ARGUMENT (4)


적어도 당신의 대답은 위 의 @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 %

특수한 상황들:

  • 아이폰 X (3072MB) : 50 %
  • iPhone XS / XS Max (4096MB) : 55 %
  • 아이폰 XR (3072MB) : 63 %
  • iPhone 11/11 Pro Max (4096MB) : 54 %-55 %

장치 RAM을 쉽게 읽을 수 있습니다.

[NSProcessInfo processInfo].physicalMemory

내 경험상 1GB 장치의 경우 45 %, 2 / 3GB 장치의 경우 50 %, 4GB 장치의 경우 55 %를 사용하는 것이 안전합니다. macOS의 백분율이 약간 더 클 수 있습니다.


업데이트 : iPhone X는 예외 인 것 같습니다-RAM의 50 %가 사용되면 (iOSMemoryBudgetTest 앱으로 테스트) 충돌합니다. 목록을 업데이트했습니다.
Slyv

0

위의 많은 답변을 사용 os_proc_available_memory()하여 iOS 13 + 용 Apples의 새로운 방법 을 구현 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.