【问题标题】:Get amount of memory used by app in iOS获取iOS中应用程序使用的内存量
【发布时间】:2012-04-14 11:47:02
【问题描述】:

我正在开发一个在上传前拆分文件的上传应用程序。它拆分文件以防止因使用过多内存而被 iOS 关闭,因为某些文件可能相当大。如果我可以设置最大内存使用量并使用它来确定大小,而不是设置最大“块”大小,那就太好了。

类似的东西

#define MAX_MEM_USAGE 20000000 //20MB
#define MIN_CHUNK_SIZE 5000   //5KB

-(void)uploadAsset:(ALAsset*)asset
{
    long totalBytesRead = 0;
    ALAssetRepresentation *representation = [asset defaultRepresentation];
    while(totalBytesRead < [representation size])
    {
        long chunkSize = MAX_MEM_USAGE - [self getCurrentMemUsage];
        chunkSize = min([representation size] - totalBytesRead,max(chunkSize,MIN_CHUNK_SIZE));//if I can't get 5KB without getting killed then I'm going to get killed
        uint8_t *buffer = malloc(chunkSize);
        //read file chunk in here, adding the result to totalBytesRead
        //upload chunk here
    }
}

基本上就是我想要的。我似乎无法找到一种方法来专门获取我的应用程序的当前内存使用情况。我并不关心剩余的系统内存量。

我能想到的唯一方法是我不太喜欢的方法。在我的应用程序的第一行获取系统内存量,然后将其存储在全局类中的静态变量中,然后 getCurrentMemUsage 会像这样

-(long)getCurrentMemUsage
{
    long sysUsage = [self getSystemMemoryUsed];
    return sysUsage - [Globals origSysUsage];
}

这有一些严重的缺点。对我来说最明显的是另一个应用程序可能会在我的上传过程中被杀死,这可能会使 sysUsage 低于 origSysUsage 从而导致负数,即使我的应用程序使用 10MB 内存,这可能导致我的应用程序使用 40MB一个请求,而不是 20MB 的最大值。我总是可以设置它,以便将值限制在 MIN_CHUNK_SIZE 和 MAX_MEM_USAGE 之间,但这只是一种解决方法,而不是实际的解决方案。

如果有任何关于获取应用程序使用的内存量或管理动态块大小的不同方法的建议,我将不胜感激。

【问题讨论】:

  • 我只会使用 256KB 的块并完成它。拥有比这更大的块有什么显着优势吗?
  • @DavidSchwartz 只是它显着加快了上传过程。用户可能正在上传超过 1gb 的文件,因此上传它需要大量的块。 20MB 会占用很多块,但仍优于 256KB(或其他更小的值)。此外,有些文件不需要完整的 20MB 内存即可上传(例如 jpeg)。我们对这个应用程序的目标是能够以尽可能少的请求尽可能快地上传,而不会耗尽内存。
  • 至少它加快了 android 上的上传过程,我敢肯定它在 iOS 设备上也是如此
  • 我会尝试弄清楚为什么您的应用程序需要如此大的缓冲区来达到最佳性能并修复它,而不是试图解决这个缺陷。
  • 我要上传到的服务器需要文件部分的顺序,所以我必须等待服务器给我一个响应,说它已经为下一部分做好了准备,然后我才能上传它。我实际上没有测试过任何大于 2MB 缓冲区和 20MB 文件的东西,但是我的请求越少,上传完成的速度就越快。在我进行文件拆分之前,20MB 的文件会非常快速地上传(因为它通过 LAN,几乎是立即上传),这就是我选择 20MB 作为理想内存使用级别的原因。

标签: iphone ios ipad ios5


【解决方案1】:

现在,与任何虚拟内存操作系统一样,获取“已使用内存”的定义并不十分明确,而且众所周知难以定义和计算。

幸运的是,感谢虚拟内存管理器,您的问题可以很容易地解决:mmap() C 函数。基本上,它允许您的应用程序将文件虚拟加载到内存中,将其视为在 RAM 中,但它实际上是在访问时从存储中换入,并在 iOS 内存不足时换出。

这个函数在 iOS 中非常容易使用,并带有 Cocoa API:

- (void) uploadMyFile:(NSString*)fileName {
    NSData* fileData = [NSData dataWithContentsOfMappedFile:fileName];
    // Work with the data as with any NSData* object. The iOS kernel
    // will take care of loading the file as needed.
}

【讨论】:

  • 不会将 NSData 添加到 POST 请求中需要整个文件并将其全部加载到内存中吗?我想我基本上已经在做同样的事情了,使用 ALAssetRepresentation 的 getBytes 方法。我跳到 totalBytesRead 并读取 chunkSize 字节,然后将其粘贴在 POST 请求上。据我所知,将 fileData 添加到请求中会同时要求所有页面,而我仍然会坐在将整个文件加载到内存中的情况下。我希望我错了,因为你的解决方案看起来很简单:)
  • 不,它不会——这就是内存映射文件的美妙之处。对于技术细节,我推荐我链接到的 Wikipedia 文章。但是,我不能说它是否解决了您的具体问题,但我建议您尝试一下。
猜你喜欢
  • 2015-07-26
  • 2018-07-27
  • 2016-02-05
  • 2012-12-11
  • 1970-01-01
  • 2013-07-06
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
相关资源
最近更新 更多