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

使用Objective-C以编程方式释放系统内存,objective-c,c,macos,cocoa,memory,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))) { re

这就是我想做的:

  • 以与
    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;
        }

    }
}
void
释放内存()
{
INTC;
字符*p,*q;
对于(c=0;c<2048;c++)
{
如果(!(p=malloc(1024*1024)))
{
返回;
}
对于(q=p;q

有什么想法吗?

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

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


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

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

一旦发生这种情况,系统中分配内存的所有内容都将在VMM交换页面时暂停。通常情况下,这只会导致局部的小延迟,但由于占用了所有可用内存,系统中的几乎所有内容都将阻塞磁盘I/O

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

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


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

该程序的执行与
清除
——它只是尝试模拟
清除
的效果。有时这是成功的,有时它只是将不必要的内存量刷新到磁盘上(这可以解释为什么您的程序在返回时可能会很慢)<代码>清除
做了一些完全不同的事情——它专注于特定的内存

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


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

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

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

至少,在RAM相对较少的系统上。在内存较大且运行应用程序的负载相对较轻的系统上,该程序将清除2GB的缓冲缓存,导致各种I/O操作变慢,因为需要从磁盘重新读取各种内容,而实际上没有任何帮助

也不应该有任何这样的事情;如果应用程序需要内存,系统会根据需要将页面从缓冲区缓存中移出和/或将内存分页到磁盘(在OS X上——在iOS上,没有能够写入脏页的寻呼机,主要是为了保持响应能力)

调用
purge
将清除各种磁盘缓冲区缓存,并模拟冷启动时的情况,但是——同样——这只会破坏系统的缓存机制,而不会实际提高用户级应用程序的性能。正如手册页所述,它对于在冷缓存状态下测试应用程序性能非常有用,但即使这样也有点可疑,因为
purge
不会逐出所有可以逐出的内容;不会干净地模拟冷态

Steve Jessep的观点很有道理,在这种情况下,调用
清除
(或类似)可能会提高性能。这通常——几乎是普遍的——在一般情况下是不成立的,因为用户进程A无法知道用户进程B、C、D、…、Z在近期或远期的任何时候可能会做什么。例子;一个用户可能会去清除内容,但RSS提要刮取器会删除几MB的XML进行解析和持久化,从而立即使清除无效。更糟糕的是,R的最后一次刷新可能在缓存中仍有一些位,这样R的刷新会增加I/O的开销,从而使其速度变慢,并且更慢
-(void)purgeRAM {
    NSTask *purgeTask = [[NSTask alloc] init];
    [purgeTask setLaunchPath:@"/usr/bin/purge"];
    [purgeTask launch];
    [purgeTask waitUntilExit];
    NSLog(@"Purge complete");
}