首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >对于小内存块的连续重新分配,应用什么算法?

对于小内存块的连续重新分配,应用什么算法?
EN

Stack Overflow用户
提问于 2018-06-06 22:10:38
回答 2查看 137关注 0票数 2

在C程序中,我面临着需要大量内存块的事务,我需要知道是否有一个算法或最佳实践技术用于处理所有这些malloc/free,我已经使用数组来存储这些内存块,但在某些时候数组本身变满了,重新分配数组只是更多的浪费,什么是优雅的方法来处理这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-06 22:31:05

在这种情况下,最好的算法是free list分配器+二进制搜索树。

您正在从系统请求一个很大的内存块,然后从这个内存块中分配固定大小的内存块。当块已满时,你可以分配另一个块,并将它们链接到红黑或AVL二进制搜索区间树中(否则在free期间通过迭代块列表来搜索块将成为一个瓶颈)

同时,多线程和线程同步也变得很重要。如果你只是简单地使用互斥锁或简单的自旋锁,你会发现libc malloc比你的自定义内存分配器快得多。可以在Hazard pointer中找到解决方案,即每个线程都有自己的内存分配器(或每个CPU核心有一个分配器)。这将增加另一个问题-当一个线程分配内存,另一个线程释放它时,这将需要在释放函数期间搜索确切的分配器,以及严格的锁定或无锁定的数据结构。

最好的选择--你可以使用jemalloctcmalloc或者任何其他通用的建议快速内存分配器来完全或部分替代你的libc (即pdmalloc)默认分配器。

票数 2
EN

Stack Overflow用户

发布于 2018-06-06 23:42:11

如果您由于所提供的功能而需要跟踪这些不同的缓冲区,那么您将需要具有某种缓冲区管理功能,其中包括为缓冲区管理分配内存。

但是,如果你担心内存碎片,那就是另一个问题了。

我已经看到了很多关于使用malloc()free()如何导致内存碎片的文章,以及减少或消除这个问题的各种方法。

我怀疑几年前,这可能是一个问题。然而,这些天来,我质疑大多数程序员是否能像开发现代编译器运行时的人一样,在管理内存方面做得很好。我确信有一些特殊的应用程序,但是编译器运行时开发非常清楚内存碎片,有许多方法可以帮助缓解这个问题。

例如,这里有一篇2010年的老文章,描述了一个现代编译器运行时实现了malloc()free()A look at how malloc works on the Mac

下面是关于GNU allocator的一些信息。

这篇来自IBM2004年11月的文章描述了内存管理Inside memory management的一些注意事项,并提供了他们所说的“用于简化malloc实现的代码和免费代码,以帮助演示内存管理所涉及的内容”。请注意,这是一个简单的示例,旨在说明一些问题,而不是对当前实践的演示。

我用Visual Studio2015做了一个快速的控制台应用程序,它在一个C源文件中调用了一个C函数,其中散布着各种大小的malloc()free()调用。我在Windows任务管理器中查看进程时运行了此程序。峰值工作集(内存)最大为34MB。在观察内存(私有工作集)的测量时,我看到它随着程序的运行而起伏不定。

代码语言:javascript
复制
#include <malloc.h>
#include <stdio.h>

void funcAlloc(void)
{
    char *p[50000] = { 0 };
    int   i;

    for (i = 0; i < 50000; i+= 2) {
        p[i] = malloc(32 + (i % 1000));
    }

    for (i = 0; i < 50000; i += 2) {
        free(p[i]); p[i] = 0;
    }
    for (i = 1; i < 50000; i += 2) {
        p[i] = malloc(32 + (i % 1000));
    }
    for (i = 1; i < 50000; i += 2) {
        free(p[i]); p[i] = 0;
    }

    for (i = 0; i < 50000; i++) {
        p[i] = malloc(32 + (i % 1000));
    }

    for (i = 0; i < 50000; i += 3) {
        free(p[i]); p[i] = 0;
    }
    for (i = 1; i < 50000; i += 3) {
        free(p[i]); p[i] = 0;
    }
    for (i = 2; i < 50000; i += 3) {
        free(p[i]); p[i] = 0;
    }
}

void funcMain(void)
{
    for (int i = 0; i < 5000; i++) {
        funcAlloc();
    }
}

在使用malloc()free()搅动内存的某些情况下,程序员应该练习帮助内存分配器的唯一考虑因素可能是对不同长度的数据使用一组标准的缓冲区大小。

例如,如果要为几个大小不同的不同数据结构创建临时缓冲区,请对所有缓冲区使用最大struct的标准缓冲区大小,以便内存管理器使用相同大小的内存块,从而能够更有效地重用空闲内存块。我见过一些动态数据结构功能使用这种方法,比如分配最小长度为32个字符的动态字符串,或者将缓冲区请求四舍五入为四或八的倍数。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50722561

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档