最好的STL容器,以避免堆碎片

时间:2016-07-04 16:43:58

标签: c++ stdvector heap-fragmentation

我有一个分析150,000个文件的程序。 Valgrind报告没有内存泄漏,但程序会随着时间的推移而减慢。

有些问题与经常使用std :: string和mktime花费太多时间有关。 (见C++ slows over time reading 70,000 files

但随着时间的推移,它仍然会放慢速度。 Lotharyx建议容器使用导致堆碎片。

我阅读了不同STL容器的优缺点的各种流程图,但我还没有完全理解。

在下面的伪代码中,我不确定我是否做出了正确的选择以避免堆碎片。

fileList.clear()
scan all disks and build "fileList", a std::set of file paths matching a pattern.

// filepaths are named by date, eg 20160530.051000, so are intrinsically ordered 

foreach(filePath in fileList)
{
    if (alreadyHaveFileDetails(filePath))
        continue;

    // otherwise
    collect file details into a fileInfoStruct;  // like size, contents, mod 

    fileInfoMap[time_t date] = fileInfoStruct;
}

// fileInfoMap is ordered collection of information structs of about 100,000 files

// traverse the list in order
foreach (fileInfo in fileInfoMap)
{
    if (meetsCondition(fileInfo))
    {
        TEventInfo event = makeEventInfo()
        eventList.push_back(event);
    }
}

上述顺序永远重复。

因此,对于容器的选择,我已经使用过(或需要):

fileList - 包含150,000个路径名的唯一字符串列表 我选择了std :: set,因为它会自动处理重复项并自动维护排序顺序。 没有随机访问,只添加条目,对它们进行排序(手动或自动),然后迭代它们。

fileInfoMap - 由与文件日期对应的time_t时间戳键入的结构数组。 我选择了std :: map。它也有150,000个条目,因此占用了大量内存。 没有随机访问权限,只将条目添加到一端。必须迭代它们,如有必要,从中间删除条目。

eventList - 一个"事件的小清单"结构,说50项。 我选择了std :: vector。不知道为什么真的。 没有随机访问,只在一端添加条目,然后迭代集合。

我对C ++很新。谢谢你的考虑。

1 个答案:

答案 0 :(得分:2)

关于内存管理,容器属于两个大的系列:将所有元素分配在一起的系列,以及分别分配元素的系列。

vector和deque属于第一个系列,列表,设置并映射到第二个。

当从不支持全局重定位的容器中不断添加和删除元素时,会出现内存碎片。

避免此问题的一种方法是使用vector,使用" reserve"预测内存需要减少重定位,并在插入时保持数据排序。

另一种方法是使用"基于链接的容器" (如列表,设置等)为它们提供一个分配器,从较大的块分配内存,回收它们而不是为每个元素插入/删除调用原始malloc / free。

查看std::allocator

您可以通过从std :: allocator派生并覆盖allocate / deallocate函数来添加所有必需的逻辑,并将yourallocator作为可选模板参数传递,轻松编写分配器。你想要使用的容器。