避免在C中的结构分配中的malloc/自由开销



我正在阅读和实验这本书的指针,

http://shop.oreilly.com/product/0636920028000.do

在本书的第6章中,>避免使用malloc/free开销标题作者在进行大量结构内存分配/交易时,建议如何避免Malloc/Free开销。

以下是他写下功能的方式

#define LIST_SIZE 10
Person *list[LIST_SIZE];
void initializeList() 
{
    int i=0;
    for(i=0; i<LIST_SIZE; i++) 
    {
        list[i] = NULL;
    }
}
Person *getPerson() 
{
    int i=0;
    for(i=0; i<LIST_SIZE; i++) 
    {
        if(list[i] != NULL) 
        {
            Person *ptr = list[i];
            list[i] = NULL;
            return ptr;
        }
    }
    Person *person = (Person*)malloc(sizeof(Person));
    return person;
}
void deallocatePerson(Person *person) 
{
    free(person->firstName);
    free(person->lastName);
    free(person->title);
}
Person *returnPerson(Person *person)
{
    int i=0;
    for(i=0; i<LIST_SIZE; i++) 
    {
    if(list[i] == NULL) 
        {
            list[i] = person;
            return person;
        }
    }
    deallocatePerson(person);
    free(person);
    return NULL;
}

我从他的代码中了解的是,他创建了一个内存池阵列,指向 struct Person type,然后用null初始化每个数组元素。

接下来,我们将使用 getPerson 函数从池中获得内存。此功能,对!= null 检查,我认为每次都会失败。因此,同样会一样,因为做malloc和内存不会随时从池中分配。

  1. 我的理解正确吗?
  2. 这是处理开销的方式吗?
  3. 正确的方法应该是什么?任何来源/链接都将不胜感激。

接下来,我们将使用GetPerson函数从池中获得内存。此功能,对!=NULL进行检查,我认为每次都会失败。

只要您继续反复致电getPerson,则该检查将每次失败。但是,如果您将getPersonreturnPerson的混合物混合在一起,则某些NULL检查将成功,因为returnPerson将非NULL值放入数组中。

此观察是理解方法的关键:该数组是已分配给mallocstruct Person块的小临时存储,但不再使用。如果有可用的话,您的代码不是再次致电malloc,而是从此特殊列表中获取可用块。

在您进行数千个分配的情况下,但在任何给定时间中都不保留比LIST_SIZE对象多的情况,malloc调用的数量仅限于LIST_SIZE

这是处理开销的方式吗?

这是使用LookAside列表的一种变体,这是一种非常重要的优化技术,以至于Microsoft创建了用于在驱动程序代码中使用的API。一种更简单的方法将使用Person *list[LIST_SIZE]用作已发布的块的堆栈,即最后发布块的索引,没有循环。

另一种方法是设置此类块的链接列表,重用块本身的内存以存储next指针。不过,此技术对于入门嘘声可能太复杂了。

首先,您的作者指的是在这里指的是什么?对于动态内存分配,我们调用malloc分配内存和free以释放内存。同样在此过程中,操作系统也需要从堆中搜索可用的内存并分配相同的内存。为了避免这种开销,他只是建议一开始,当您的应用程序加载以及您知道可能的动态内存分配到struct的频率,您可以提前保留一个存储器库,这将减少内存的分配和交易分配高架高度。在一定程度上,如果您的服务器已经运行了很多应用程序,并且处理器很忙,则可以采用这种方法。但是也有缺点。在这种情况下,您已经提前从堆中保留了一个内存池。如果未正确使用,它将导致内存管理差。

我认为示例的重点可能是 Person对象将指针固定在其他内存中。我们可以从deallocatePerson函数中看到,结构内有3个指针:

void deallocatePerson(Person *person) 
{
    free(person->firstName);
    free(person->lastName);
    free(person->title);
}

这意味着要构建一个完整的Person,您需要几个呼叫malloc(结构本身为1,字符串为3(。

因此,通过保存完整的结构(包括其字符串(,一个getPerson呼叫替换四个呼叫malloc。这可能会节省某些执行时间。

否则,如果malloc/ free内部保存了类似的数组或链接的列表,我不会感到惊讶。如果您只有free'D正确大小的内存块,则可以将malloc的新调用定位为非常 fast。

Person是一个简单的结构(。

最新更新