在iOS中观察内存使用情况

时间:2011-11-03 03:12:14

标签: iphone ios

有没有办法找出iOS中可用的内存量?我知道当可用内存不足时,系统会传递低内存警告。但是,我的应用程序有一些点,单个线程将执行复杂的任务,有时该任务耗尽足够的内存,它只是由操作系统终止(我的应用程序可以从互联网上下载图片,我将它们缩小到一个小大小...如果用户下载了一个非常大的图像,我的应用程序内存不足,只是“噗”。

让应用程序自发终止显然是一种糟糕的用户体验。

当我即将耗尽内存并停止执行任务时,有什么方法可以找出来吗?

我想我可以将任务放在一个单独的线程上,也许系统会向主线程发送一个低内存警告,但这看起来很复杂,甚至不能保证工作。

谢谢! 罗恩

7 个答案:

答案 0 :(得分:93)

在使用XCode测试和调试您的应用程序时,您可以使用此logMemUsage()功能来NSLog使用/可用空间并观察测试应用程序时的情况。此功能记录使用中的任何更改> 100KB。它像这样输出到调试日志(在模拟器上,可用空间很大):

2011-11-02 21:55:58.928 hello[971:207] Memory used 21884.9 (+21885), free 1838366.8 kb
2011-11-02 21:55:59.936 hello[971:207] Memory used 28512.3 (+6627), free 1830809.6 kb
2011-11-02 21:56:01.936 hello[971:207] Memory used 28803.1 ( +291), free 1830129.6 kb
2011-11-02 21:56:02.936 hello[971:207] Memory used 29712.4 ( +909), free 1830142.0 kb

您决定在应用中拨打logMemUsage的位置。我碰巧有一个每秒钟都被一个计时器调用的函数,所以我把它放在那里。我建议在这些周围使用#ifdef,这样这段代码只包含在Debug版本中。

#import "mach/mach.h" 

vm_size_t usedMemory(void) {
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
    return (kerr == KERN_SUCCESS) ? info.resident_size : 0; // size in bytes
}

vm_size_t freeMemory(void) {
    mach_port_t host_port = mach_host_self();
    mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    vm_size_t pagesize;
    vm_statistics_data_t vm_stat;

    host_page_size(host_port, &pagesize);
    (void) host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
    return vm_stat.free_count * pagesize;
}

void logMemUsage(void) {
    // compute memory usage and log if different by >= 100k
    static long prevMemUsage = 0;
    long curMemUsage = usedMemory();
    long memUsageDiff = curMemUsage - prevMemUsage;

    if (memUsageDiff > 100000 || memUsageDiff < -100000) {
        prevMemUsage = curMemUsage;
        NSLog(@"Memory used %7.1f (%+5.0f), free %7.1f kb", curMemUsage/1000.0f, memUsageDiff/1000.0f, freeMemory()/1000.0f);
    }
}

答案 1 :(得分:3)

实际上每个视图控制器都有- (void)didReceiveMemoryWarning个函数。

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

根据评论的建议,您可以在评论下发布未使用的数据。另一方面,注释掉[super didReceiveMemoryWarning];来抑制内存警告&amp;自动释放对象。

答案 2 :(得分:3)

首先,您的问题的标题是如何在iOS中观看内存使用。有一个名为instrument的工具附带xcode,您可以使用它来跟踪内存分配,泄漏,CPU使用和许多其他事情。请参阅关于主题的苹果documentation ..

  • 现在查看您可以使用的应用的实时内存使用情况 仪器中的分配器工具
  • 要识别内存泄漏,您可以使用仪器中的泄漏工具..

同样在WWDC 2010中,有video如何使用Instrument来分析内存..

答案 3 :(得分:3)

我建议您查看Nimbus的概述工具,以便实时查看设备统计信息。开箱即用它包括用于查看可用内存,磁盘空间和日志以及修改日志级别的页面。添加显示所需信息的自定义页面也很容易。

http://latest.docs.nimbuskit.info/NimbusOverview.html

Nimbus' Overview Tool

答案 4 :(得分:2)

apple提供的一套开发工具包括“Instruments”。您可以使用它来监视分配和泄漏。在Xcode中,如果长按“运行”按钮,您将看到一个名为“配置文件”的选项。这将自动打开仪器,并允许您选择配置文件来监控您的应用程序。

答案 5 :(得分:2)

我喜欢免费代码。谢谢progrmr,非常有用。是时候让我开始分享了。我根据自己的用例反对它。

#import "mach/mach.h"
#import "memusage.h"



@implementation memusage

static long prevMemUsage = 0;
static long curMemUsage = 0;
static long memUsageDiff = 0;
static long curFreeMem = 0;

-(vm_size_t) freeMemory {
    mach_port_t host_port = mach_host_self();
    mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    vm_size_t pagesize;
    vm_statistics_data_t vm_stat;

    host_page_size(host_port, &pagesize);
    (void) host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
    return vm_stat.free_count * pagesize;
}

-(vm_size_t) usedMemory {
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
    return (kerr == KERN_SUCCESS) ? info.resident_size : 0; // size in bytes
}

-(void) captureMemUsage {
    prevMemUsage = curMemUsage;
    curMemUsage = [self usedMemory];
    memUsageDiff = curMemUsage - prevMemUsage;
    curFreeMem = [self freeMemory];


}

-(NSString*) captureMemUsageGetString{
    return [self captureMemUsageGetString: @"Memory used %7.1f (%+5.0f), free %7.1f kb"];
}

-(NSString*) captureMemUsageGetString:(NSString*) formatstring {
    [self captureMemUsage];
     return [NSString stringWithFormat:formatstring,curMemUsage/1000.0f, memUsageDiff/1000.0f, curFreeMem/1000.0f];

}

@end

答案 6 :(得分:1)

听起来您可以使用精心设计的库来获取Web图像。 Nimbus has got a Network Image class which does that efficiently