ngân sách bộ nhớ tối đa của ứng dụng ios


152

Tôi đang làm việc trên một trò chơi ios nhắm mục tiêu tối thiểu là 3gs. Chúng tôi đang sử dụng tài sản HD cho các thiết bị hiển thị võng mạc (iphone 4, ipod touch thế hệ thứ 4).

Thông minh về bộ nhớ, Ipod Touch thế hệ thứ 4 dường như là thiết bị hạn chế nhất đối với chúng tôi vì nó có cùng dung lượng RAM (256 so với 512 của Iphone 4) như 3g nhưng chúng tôi đang sử dụng tài sản HD trên đó. Ứng dụng đã từng gặp sự cố khi cố tải 100-110mb ram nhưng hiện tại chúng tôi đã giảm xuống còn 70 MB, chúng tôi chưa bao giờ tải sự cố.

Sau rất nhiều lần tìm kiếm xung quanh, dường như không có giới hạn cứng chính thức, vậy chúng ta nên tìm hiểu ngân sách bộ nhớ nào để an toàn? Chúng tôi muốn có thể cung cấp cho các nghệ sĩ một ngân sách mà họ có thể sử dụng mà không phải lo lắng về bộ nhớ cho mỗi bản đồ.



14
Không chắc làm thế nào câu hỏi này có thể là một bản sao của một cái gì đó đã được hỏi tại một thời điểm sau đó.
Jasper

Câu trả lời:


42

Tôi nghĩ bạn đã trả lời câu hỏi của riêng mình: cố gắng không vượt quá giới hạn 70 Mb, tuy nhiên điều này thực sự phụ thuộc vào nhiều thứ: phiên bản iOS nào bạn đang sử dụng (không phải SDK), có bao nhiêu ứng dụng chạy nền, bộ nhớ chính xác là gì bạn đang sử dụng vv

Chỉ cần tránh các bộ nhớ tức thời (ví dụ: bạn đang sử dụng 40 Mb RAM, sau đó phân bổ thêm 80 Mb cho một số tính toán ngắn). Trong trường hợp này, iOS sẽ giết ứng dụng của bạn ngay lập tức.

Bạn cũng nên xem xét việc lười tải tài sản (chỉ tải chúng khi bạn thực sự cần chứ không phải trước đó).


2
Chỉ là chúng tôi muốn đặt nhiều thứ nhất có thể (đồ họa & âm thanh). Các nghệ sĩ sẽ luôn muốn đưa càng nhiều càng tốt vào một trò chơi, đó là lý do tại sao tôi muốn giới hạn họ bằng ngân sách. Tôi đoán chúng ta sẽ phải thử nghiệm trên nhiều thiết bị khác nhau trong các cài đặt khác nhau để tìm ra dung lượng bộ nhớ tối đa hợp lý để sử dụng.
frilla

2
Việc chỉ phân bổ 70 MB (có lẽ nằm trong ngân sách) bất cứ lúc nào trên thiết bị đó (ngay cả sau khi sử dụng nhiều trong các ứng dụng ngốn bộ nhớ khác) luôn đảm bảo phân bổ thành công, hoặc có khả năng nó vẫn bị sập không?
Steven Lu

1
@Steven Lu nó phụ thuộc vào thiết bị của bạn. Ví dụ, trên những cái mới hơn, như phân bổ iPhone5 hoặc iPad4 70 Mb hoàn toàn không phải là vấn đề.
Tối đa

1
có nhưng tôi muốn biết liệu tôi có thể chắc chắn rằng miễn là tôi giữ tổng mức sử dụng của ứng dụng trong ngân sách bộ nhớ cụ thể của thiết bị ma thuật mà nó sẽ không bị chấm dứt!
Steven Lu

1
không có gì đảm bảo
Tối đa

421

Kết quả kiểm tra với tiện ích Split đã viết (liên kết nằm trong câu trả lời của anh ấy):

thiết bị: (số tiền sự cố / tổng số tiền / phần trăm của tổng số)

  • iPad1: 127MB / 256MB / 49%
  • iPad2: 275MB / 512MB / 53%
  • iPad3: 645MB / 1024MB / 62%
  • iPad4: 585MB / 1024MB / 57% (iOS 8.1)
  • iPad Mini thế hệ 1: 297MB / 512MB / 58%
  • Võng mạc 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 số: 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)
  • iPod touch thế hệ thứ 4: 130MB / 256MB / 51% (iOS 6.1.1)
  • iPod touch thế hệ thứ 5: 286MB / 512MB / 56% (iOS 7.0)
  • iPhone4: 325MB / 512MB / 63%
  • iPhone4: 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 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 Max: 2067/3740 / 55% (iOS 13.2.3)

2
iPhone4: giá trị tương tự được xác nhận, có vẻ hợp pháp: P
cprcrack

3
iPhone 5 gặp sự cố ở mức ± 645 MB.
asp_net

4
@JasperPol Tôi đã chỉnh sửa bài đăng của bạn để bao gồm nhiều thiết bị khác nhau mà tôi có, tôi hy vọng điều đó ổn. Tôi đã thêm phiên bản iOS mà tôi đã thử nghiệm trong trường hợp có vấn đề, nhưng vui lòng xóa nó nếu bạn cho rằng nó không quan trọng.
JosephH

2
Tuyệt vời rằng danh sách này đã được tạo và duy trì. Theo kinh nghiệm của tôi, tôi đã phải giữ bộ nhớ thấp hơn nhiều để an toàn, có thể là 20% những gì được hiển thị ở đây. Sự khác biệt giữa thiết bị với thiết bị cũng rất khác nhau.
dùng1021430

1
Chỉ cần chạy nó trên iPad Pro 12.9. Cảnh báo bộ nhớ ở mức 2451MB, sự cố ở mức 3064 MB, tổng cộng 3981 MB.
khóa

134

Tôi đã tạo ra tiện ích nhỏ cố gắng phân bổ càng nhiều bộ nhớ càng tốt để khắc phục sự cố và nó ghi lại khi cảnh báo và sự cố bộ nhớ xảy ra. Điều này giúp tìm ra ngân sách bộ nhớ cho bất kỳ thiết bị iOS nào.

https://github.com/Split82/iOSMemoryB líTest


Tôi đã thực hiện một thử nghiệm thú vị: chạy ứng dụng của mình với việc sử dụng bộ nhớ theo dõi xcode, nhập nền, chạy BudgetTest. Thử nghiệm đã bị giết trong khi ứng dụng trong nền của tôi thì không. Tôi muốn biết tại sao. Ngoài ra, điều này đi ngược lại với những gì @cprcrack đã nói trong câu trả lời khác.
Roberto

19

Trong ứng dụng của tôi, trải nghiệm người dùng sẽ tốt hơn nếu sử dụng nhiều bộ nhớ hơn, vì vậy tôi phải quyết định xem tôi có thực sự nên giải phóng tất cả bộ nhớ tôi có thể không didReceiveMemoryWarning. Dựa trên câu trả lời của Split và Jasper Pol, sử dụng tối đa 45% tổng bộ nhớ thiết bị dường như là ngưỡng an toàn (cảm ơn các bạn).

Trong trường hợp ai đó muốn xem xét triển khai thực tế của tôi:

#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 (dựa trên câu trả lời này ):

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
kích thước phải là TASK_BASIC_INFO_COUNT thay vì sizeof (thông tin) - lỗi này được sao chép vào nhiều nơi có cùng mã
Maxim Kholyavkin

Cảm ơn Sayus. Bạn có vẻ đúng dựa trên liên kết này . Bạn có bất kỳ tài liệu tham khảo nào khác nơi thông tin này có thể được tìm thấy?
cprcrack

táo sử dụng TASK_BASIC_INFO_COUNT quá
Maxim Kholyavkin

45% không còn giới hạn an toàn nữa, nó quá gần với 50% giá trị sự cố cho iPhone X. Tôi khuyên bạn nên sử dụng 40% hoặc giá trị riêng cho từng thiết bị.
Slyv

8

Bằng cách yêu cầu repo SPLITS, tôi đã tạo một cái để kiểm tra bộ nhớ iOS có thể được phân bổ cho Tiện ích mở rộng hôm nay

iOSMemoryB líTestForExtension

Sau đây là kết quả mà tôi nhận được trong iPhone 5s

Cảnh báo bộ nhớ ở mức 10 MB

Ứng dụng bị sập ở mức 12 MB

Điều này có nghĩa là Apple chỉ đơn thuần cho phép bất kỳ tiện ích mở rộng nào hoạt động với tiềm năng đầy đủ của chúng .


7

Bạn nên xem phiên 147 từ video Phiên WWDC 2010 . Đó là "Tối ưu hóa hiệu suất nâng cao trên HĐH iPhone, phần 2".
Có rất nhiều lời khuyên tốt về tối ưu hóa bộ nhớ.

Một số lời khuyên là:

  • Sử dụng NSAutoReleasePools lồng nhau để đảm bảo việc sử dụng bộ nhớ của bạn không tăng đột biến.
  • Sử dụng CGImageSourcekhi tạo hình thu nhỏ từ hình ảnh lớn.
  • Đáp ứng với các cảnh báo bộ nhớ thấp.

Câu hỏi của tôi không phải là về cách tối ưu hóa (cảm ơn vì liên kết mặc dù), đó là về việc chúng ta có thể cho phép mình sử dụng bao nhiêu. Lý do là, ví dụ, nếu chúng tôi tối ưu hóa để đạt được 20mb, thì các nghệ sĩ sẽ muốn sử dụng 20mb đó nếu nó nằm trong "ngân sách" hợp lý, hay chắc chắn rằng nó sẽ không gây ra bất kỳ vấn đề nào về hiệu suất hoặc sự cố bộ nhớ.
frilla

ĐỒNG Ý. Sự cố sẽ là do HĐH đang chấm dứt ứng dụng vì bộ nhớ bị hạn chế. Bạn chỉ có thể thêm một NSLogbên trong didReceiveMemoryWarningvà sau đó thực hiện một số thử nghiệm trong đó bạn phân bổ số lượng bộ nhớ khác nhau và sau đó xem khi nào cảnh báo bộ nhớ bắt đầu khởi động.
Kobski

4

Bắt đầu với iOS13, có một cách truy vấn được Apple hỗ trợ bằng cách sử dụng

#include <os/proc.h>

size_t os_proc_available_memory(void)

Được giới thiệu tại đây: https://developer.apple.com/ideo/play/wwdc2019/606/

Khoảng tối thiểu 29-ish.

Chỉnh sửa: Thêm liên kết vào tài liệu https://developer.apple.com/documentation/os/3191911-os_proc_av Available_memory? Lingu = objc


Cuối cùng! Tôi đã thử nghiệm os_proc_av Available_memory () trên một số thiết bị và kết quả rất giống với các giá trị i bảng lớn ở trên!
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;
}

Nếu một người sẽ sử dụng TASK_BASIC_INFO_COUNT thay vì Mach_TASK_BASIC_INFO, bạn sẽ nhận được

kerr == Kern_INVALID_ARGUMENT (4)


Ít nhất bạn nên đề cập rằng câu trả lời của bạn gần như là một bản sao và dán chính xác của @ cprcrack ở trên. Sự khác biệt duy nhất là TASK_BASIC_INFO_COUNT.
mrvincenzo

2

Tôi đã tạo thêm một danh sách bằng cách sắp xếp danh sách Jaspers theo RAM thiết bị (Tôi đã tự kiểm tra bằng công cụ của Split và sửa một số kết quả - kiểm tra nhận xét của tôi trong luồng Jaspers).

RAM thiết bị: phạm vi phần trăm bị sập

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

Trường hợp đặc biệt:

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

RAM thiết bị có thể được đọc dễ dàng:

[NSProcessInfo processInfo].physicalMemory

Theo kinh nghiệm của tôi, an toàn khi sử dụng 45% cho thiết bị 1GB, 50% cho thiết bị 2 / 3GB và 55% cho thiết bị 4GB. Phần trăm cho macOS có thể lớn hơn một chút.


cập nhật: Có vẻ như iPhone X là một ngoại lệ - nó gặp sự cố khi sử dụng 50% RAM (được thử nghiệm với ứng dụng iOSMemoryB líTest). Tôi đã cập nhật danh sách.
Slyv

0

Làm việc với nhiều câu trả lời ở trên, tôi đã triển khai phương pháp mới Táo os_proc_available_memory()cho iOS 13+ cùng với NSByteCountFormatterđó cung cấp một số tùy chọn định dạng hữu ích cho đầu ra đẹp hơn của bộ nhớ:

#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]);
    }
}

Lưu ý quan trọng: Đừng quên ()phần cuối. Tôi đã bao gồm cả hai NSLogtùy chọn trong memoryLoggingOutputphương thức vì nó không cảnh báo bạn rằng chúng bị thiếu và không bao gồm dấu ngoặc trả về kết quả bất ngờ nhưng không đổi.

Chuỗi được trả về từ các memoryStringForBytesgiá trị đầu ra của phương thức như vậy:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.