你认为不为小程序释放内存是个好主意吗?

时间:2014-06-03 16:58:14

标签: c++ c linux

让我们说我的系统有4GB的RAM,某个程序在执行过程中只消耗100 MB的内存,并且运行时间有限,只有30秒。难道你不认为在执行该程序期间根本不释放内存是一个好主意(通过提高性能)吗?无论如何,在该程序终止时,这些100 MB将被释放。

4 个答案:

答案 0 :(得分:7)

在短期运行的程序中释放内存最重要的部分是精简内存重用。你的处理器有一个有限的缓存,可能只有几MB,如果你不断分配更多的内存,你就永远无法利用它。

但是,如果您释放一些内存,然后重新分配并重新使用它,那么在重用时,内存很可能已经“热”并驻留在缓存中。这意味着您不会因高速缓存未命中而受到惩罚,并且您的程序将运行得更快。

当然,您正在考虑缓存未命中的重新分配/重新分配成本,但是不断分配越来越多的内存可以保证产生最低级别的缓存未命中。这些缓存未命中中的每一个都在现代处理器上花费大约100条指令,比分配/解除分配的成本低。

修改

所以我做了一个小测试程序来测试它。

#include <stdio.h>
#include <stdlib.h>

process1(){
    char * ptr = malloc(1 << 20);
    int i = 0;
    while (i < (1<<20)) ptr[i++] = rand();
    free(ptr);
}

process2(){
    char * ptr = malloc(1 << 20);
    int i = 0;
    while (i < (1<<20)) ptr[i++] = rand();
}


main(){
    int i = 100;
    while(i--) process1();
    i = 100;
    while(i--) process2();
}

两个进程都会通过100 MB的数据进行咀嚼,第一个进程会释放数据,第二个进程不进行解析。我用valgrind的cachegrind工具来描述这个。结果如下

fn=process1
0 943720200 2 2 419430900 100 0 209715800 1638400 32767
fn=process2
0 943719900 0 0 419430800 100 0 209715700 1638400 1605784

好的不是那么令人兴奋,我会翻译。通过避免释放,您节省了不到0.1%的指令周期,并且您导致大约一百五十个LL缓存未命中。如果我们使用标准循环估计公式CEst = lr + 10 Llm + 100 LLm,其性能降低约16%,从而避免单独使用该函数。

我在callgrind中重新获取完整的故事(我不会发布详细的结果,因为它们比缓存研磨更复杂)但是当我们将完整的调用包含在free中时,结果是相同的,a当您不拨打免费电话时,会使用16%以上的周期。

随意在您自己的程序上进行相同的测试,但在这种情况下,结果很清楚。与使用新内存不断刷新缓存的成本相比,管理动态内存的成本确实微不足道。

另外,我没有提到这一点,但应该进行的直接比较是免费降低高速缓存成本。免费总共花费38930个周期,缓存未命中157332000,您节省了39000个周期,并为其支付了1.5亿个。

答案 1 :(得分:6)

Don't you think its a good idea not to deallocate memory at all during the execution of that program?

切角不是一个好主意&#34;。我可以想出释放记忆的充分理由;我不能想到分配未使用的内存这么多。如果您不想处理内存问题,请不要使用没有自动垃圾收集的语言 - 或者,因为您使用C ++编写,请使用{{3 }}

only consumes 100 MB of memory

这是对“#34;”这个词的最严重滥用;我见过。 100 MB是一个重要的变化。这是您正在使用的内存的1/40,如果在系统上运行的其他40个程序都是以相同的视角编程的,那么您最好让系统进行磨削由于交换延迟而停止,最坏的情况是您有完整的系统崩溃。通常,在任何给定(现代)机器上运行的应用程序超过40个。

also runs for a limited time, like only 30 seconds

同样,计算机需要30秒才能完成。但是,澄清一下,你的意思是永远 30秒,还是每天30秒?因为如果它是一次性的而且你的时间很短,那么这可能是一种可以接受的损失,但这当然不是一种好的做法。

TL; DR

如果您有更重要的,即时的考虑因素(例如产品截止日期临近),而您没有其他合理的选择,那就去做吧。否则,你没有任何借口。慢跑记忆绝不是你应该感觉良好的东西;它可以严重减慢真正需要该内存的进程。是的,O / S在程序结束后清理资源。不,这并不能让您全权编写滥用其资源的程序。

答案 2 :(得分:2)

不,这不是很好的编程风格。事实上,所有现代操作系统都会在之后清理内存,但只要程序运行,它就会一直存在漏洞。

答案 3 :(得分:0)

如果你想避免清理开销,你可以实现一个允许这样做的分配器,同时仍然保持良好的实践。例如,在程序启动时分配内存池,将全局operator new替换为从池中获取内存的版本,并将全局operator delete替换为no-op。然后在程序退出之前释放内存池。您还可以使用更多查找粒度池来减少重新分配开销,但仍允许程序在不增加内存使用量的情况下运行。

另一种方法是简单地使用new / delete的更快实现。内置版本传统上很慢,但它们不一定非。

相关问题