3

所以,这就是我想要做的:

  • 以与命令相同的方式释放系统内存(非活动内存),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;
        }

    }
}

有任何想法吗?

4

5 回答 5

23

现实情况是代码没有做——也永远不会做——它声称的。这是垃圾。

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

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

也不应该有任何这样的事情;如果应用程序需要内存,系统将根据需要从缓冲区缓存中逐出页面和/或将内存分页到磁盘(在 OS X 上——在 iOS 上,没有分页器能够在很大程度上写入脏页以保持响应能力)。

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

对于 Steve Jessep 的观点,在某些情况下调用purge(或类似的)可能会提高性能。这通常 - 几乎普遍 - 在一般情况下分崩离析,因为用户进程 A 无法知道用户进程 B、C、D、....、Z 在附近或遥远的未来。例子; A 可能会去清除东西,只是让 RSS Feed Scraper R 撕下几 MB 的 XML 进行解析和持久化,立即使清除无效。更糟糕的是,R 的最后一次刷新可能仍有一些位潜伏在缓存中,因此 R 的刷新会影响 I/O,使其变得更慢且成本更高(包括消耗电池寿命)。

于 2012-09-05T17:14:23.733 回答
6

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

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

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

于 2012-09-05T08:47:27.433 回答
4

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

一旦发生这种情况,系统中分配内存的所有内容都会在 VMM 交换页面时停止。通常这只会在这里和那里造成小的延迟,但是由于您正在占用所有可用内存,因此系统中的几乎所有内容都会在磁盘 I/O 上阻塞。

我相当有信心,如果您等待的时间足够长,VMM 会赶上来,系统会恢复正常。

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

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

于 2012-09-05T09:00:39.120 回答
3

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

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

FWIW,这在 10.8 中的问题比 10.7 小。

于 2012-09-05T09:45:44.860 回答
1

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

-(void)purgeRAM {
    NSTask *purgeTask = [[NSTask alloc] init];
    [purgeTask setLaunchPath:@"/usr/bin/purge"];
    [purgeTask launch];
    [purgeTask waitUntilExit];
    NSLog(@"Purge complete");
}
于 2013-08-15T01:30:11.103 回答