使用Objective-C以编程方式释放系统内存

时间:2012-09-05 08:37:59

标签: objective-c c macos cocoa memory

所以,这就是我要做的事情:

  • purge命令执行的方式释放系统内存(非活动内存),但是以编程方式执行。

我在这里尝试了代码(其作者声称它有效),但它所做的只是让Mac OS X冻结:

void
free_up_memory()
{
    int c;
    char *p, *q;

    for(c = 0; c < 2048; c++)
    {
        if(!(p = malloc(1024 * 1024)))
        {

            return;
        }
        for(q = p; q < p + (1024 * 1024); q += 4096)
        {
            *q = 1;
        }

    }
}

有什么想法吗?

5 个答案:

答案 0 :(得分:23)

现实是代码没有 - 而且永远不会 - 它声称的东西。这是垃圾。

它所要做的就是破坏系统的缓冲区缓存子系统,并可能使机器迅速进入分页状态,导致看起来像锁定的症状。特别是在具有慢速(例如5,400rpm笔记本电脑驱动器)硬盘驱动器的系统上。

至少在RAM数量相对较少的系统上。在具有大量RAM和相对较轻的应用程序运行的系统上,该程序将驱逐2GB的缓冲区缓存,导致各种I / O操作变慢,因为需要从磁盘重新读取各种内容,而不是真的帮忙。

任何此类事情都不是必要的;如果一个应用程序需要内存,系统将根据需要从缓冲区缓存中逐出页面和/或将内存分页到磁盘(在OS X上 - 在iOS上没有能够编写脏页的寻呼机,主要是为了保持响应性)。

调用purge将驱逐各种磁盘缓冲区缓存并模拟冷启动时的条件,但是 - 再次 - 这只会破坏系统的缓存机制,而不会实际提高用户级应用程序的性能。作为手册页文档,它对于在冷缓存状态下测试应用程序性能非常有用,但即使这有点可疑,因为purge不会驱逐所有可能的内容驱逐;不会干净地模拟冷态。

对于Steve Jessep来说,非常有效的一点是,在某些情况下,调用purge(或类似内容)可能会提高性能。这通常 - 几乎普遍 - 在一般情况下崩溃,因为用户进程A无法知道用户进程B,C,D,....,Z可能在附近的任何点处进行或者遥远的未来。例;一个可能去清除东西只是为了让RSS Feed Scraper R翻译掉几MB的XML进行解析和持久化,立即使清除无效。更糟糕的是,R的最后一次更新可能仍然潜伏在高速缓存中,这样R在I / O上刷新了数量,使得它更慢,成本更高(包括耗费电池寿命)。

答案 1 :(得分:6)

这段代码实际上做的是分配尽可能多的内存,在1MB块中最多可以分配2GB,并向其写入一些数据以确保内存实际提交。也就是说,确保您不仅仅分配了虚拟地址空间而且没有内存。然后就泄漏了。

因此,代码所做的是“强制操作系统执行内存不足时的操作”。然后当这个程序退出时,它的内存被释放,你有很多很好的可用空间。

这段代码的作者希望“当内存不足时操作系统会做什么”是释放你所谓的“非活动内存”。看起来它实际上为你做的就是冻结。显然这是一个错误。任何时候都有任意数量的设备和服务在运行,其中只有一个需要有缺陷而导致问题。对于操作系统冻结,问题必须是高于用户模式的运行,所以我很失望但并不感到惊讶。

答案 2 :(得分:4)

Mac OS X可能正在冻结,因为它正在等待虚拟内存管理器(VMM)将页面交换到磁盘;由于你的功能是快速分配内存,系统正在尽一切可能为它提供服务,并且它将在它放弃之前使用磁盘交换文件。

一旦发生这种情况,系统中分配内存的所有内容都将停止,而VMM正在交换页面。通常情况下,这只会导致小的延迟,但是由于你正在吸收所有可用的内存,因此系统中的所有内容几乎都会阻塞磁盘I / O.

如果你等了足够长的时间,我相当自信,VMM会赶上来,系统会恢复正常。

您可以在应用运行时查看活动监视器来测试我的假设;如果我是对的,那么当Mac被冻结时,磁盘I / O会非常高。

如果你真的想要释放内存,你应该做一些不同的事情:以编程方式执行purge命令,或用“保持内存连线”的东西替换malloc的调用(赢了)不要分页到磁盘。或者,根本不要这样做,而不是二次猜测VMM,只是让它做它的工作。

答案 3 :(得分:3)

该程序与purge的执行方式不同 - 它只是试图模拟purge的效果。有时这是成功的,有时它只是将不必要的内存量刷新到磁盘上(这可以解释为什么当你返回它们时你的程序可能会很慢)。 purge做了一些完全不同的事情 - 它专注于特定的记忆。

就“冻结”而言,一旦你达到上限,系统就会开始将内存的内容推送到磁盘。系统还将尝试释放进程中的内存支持文件节点 - 内存支持的文件节点特别是purge关注的内容。您的程序最终将其他进程的内存推送到磁盘。对于这个问题,这不是一个好的解决方案。它需要太多,而且没有选择性。无论如何......这种做法可能会像宣传的那样紧张。它与某种类似,并且可以在此过程中释放磁盘缓冲区缓存。

FWIW,这不是10.8中的问题,而不是10.7。

答案 4 :(得分:1)

这应该释放OS X认为不需要的所有RAM:

-(void)purgeRAM {
    NSTask *purgeTask = [[NSTask alloc] init];
    [purgeTask setLaunchPath:@"/usr/bin/purge"];
    [purgeTask launch];
    [purgeTask waitUntilExit];
    NSLog(@"Purge complete");
}