gha*_*der 37 memory-management
这是我的问题:调用free或delete是否会将内存释放回"system".我的意思是,系统是否会减少流程的数据段?
让我们考虑Linux上的内存分配器,即ptmalloc.
据我所知(如果我错了请纠正我),ptmalloc维护一个免费的内存块列表,当内存分配请求到来时,它会尝试从这个空闲列表中分配一个内存块(我知道,分配器很多)比这更复杂,但我只是简单地说它)但是,它失败了,它使用say sbrk或brk系统调用从系统获取内存.当一个内存被释放时,该块被放置在空闲列表中.
现在考虑这种情况,在峰值负载时,已经在堆上分配了许多对象.现在当负载减少时,对象是免费的.所以我的问题是:一旦对象被free'd将分配器做一些计算,以发现是否应该保持这个对象在免费的列表或取决于空闲列表的当前大小可能决定给内存回系统即使用sbrk或brk减少进程的数据段.
glibc的文档告诉我,如果分配请求比页面大小大得多,它将使用mmap分配,并且一旦被释放就会直接释放回系统.凉.但是让我说我从来没有要求分配大于50字节的大小,并且我在系统的峰值负载上询问了很多这样的50字节对象.那又怎样?
据我所知(指正请),使用malloc分配的内存将永远不会被释放回过,直到进程结束即分配器只会保持在空闲列表,如果我释放它的系统.但是,这是困扰我的问题是,那么,如果我用一个工具来查看我的进程的内存使用情况(我在Linux上使用PMAP,你们怎么使用呢?),它应该始终显示在高峰负荷使用的内存(因为内存永远不会返回给系统,除非使用mmap分配)?那个进程使用的内存永远不会减少(堆栈内存除外)?是吗 ?
我知道我错过了什么,所以请详细说明这一切.
专家,请清楚我的相关概念.我会很感激.我希望我能够解释我的问题.
Lar*_*abe 12
malloc没有太多开销,因此您不太可能节省任何运行时间.但是,有一个很好的理由在malloc之上实现一个分配器,那就是能够跟踪内存泄漏.例如,您可以在程序退出时释放程序分配的所有内存,然后检查内存分配器是否调用balance(即分配/取消分配的调用次数相同).
对于您的特定实现,没有理由free(),因为malloc不会释放到系统内存,因此它只会将内存释放回您自己的分配器.
使用自定义分配器的另一个原因是您可能正在分配许多相同大小的对象(即,您有一些分配很多的数据结构).您可能希望为此类对象维护单独的空闲列表,并且仅从此特殊列表中释放/分配.这样做的好处是它可以避免内存碎片.
由于多种原因,这实际上是一个糟糕的策略,因此它不会发生——除非——正如您所注意到的,对于可以直接在页面中进行的大量分配,可能会有一个例外。
它增加了内部碎片,因此实际上会浪费内存。(您只能将对齐的页面返回给操作系统,因此从块中拉出对齐的页面通常会在块的任一侧创建两个保证很小的块——无论如何都小于一个页面。如果这发生很多事情,你最终会得到相同总量的有用分配内存加上许多无用的小块。)
需要内核调用,内核调用很慢,所以会减慢程序的速度。将块扔回堆中要快得多。
几乎每个程序要么收敛于稳态内存占用,要么在退出前占用越来越大的内存。(或者,直到接近退出。)因此,页面返回机制所需的所有额外处理都将被完全浪费掉。