【发布时间】:2020-09-17 04:53:09
【问题描述】:
我正在通过以下方式处理非常大的文本文件:
class Loader{
template<class READER>
bool loadFile(READER &reader){
/* for each line of the input file */ {
processLine_(line);
}
}
bool processLine_(std::string_view line){
std::vector<std::string> set; // <-- here
std::string buffer; // <-- here
// I can not do set.reserve(),
// because I have no idea how much items I will put.
// do something...
}
void printResult(){
// print aggregated result
}
}
处理 143,000,000 条记录大约需要 68 分钟。
所以我决定对几个std::array 缓冲区进行一些非常棘手的优化。结果大约是 62 分钟。
但是代码变得非常不可读,所以我决定不在生产中使用它们。
然后我决定做部分优化,例如
class Loader{
template<class READER>
bool loadFile(READER &reader);
std::vector<std::string> set; // <-- here
std::string buffer; // <-- here
bool processLine_(std::string_view line){
set.clear();
// do something...
}
void printResult();
}
我希望这会减少来自 buffer 和 set 向量的 malloc / free (new[] / delete[]) 操作。我意识到set 向量中的字符串仍然动态分配内存。
但是结果到了 83 分钟。
请注意,除了将set 和buffer 移动到“类”级别之外,我不会更改任何内容。我只在processLine_ 方法中使用它们。
这是为什么呢? 参考地点?
我想到的唯一解释是一些字符串足够小并适合 SSO,但这听起来不太可能。
将 clang 与 -O3 一起使用
【问题讨论】:
-
在开始处理之前是否将文件的每条记录都加载到内存中?您可能会用完 RAM,而您的操作系统决定使用交换空间?如果你想减少重新分配,你可以使用某种启发式(文件大小)来预测你需要的向量元素的近似数量。数据库会比平面文件更好吗?
-
你对
set或buffer末尾的processLine_的内容或内容做了什么吗? -
@JohnFilleau 是的,但我认为这并不重要。它读取文件,然后为 txt 文件的每一行调用此函数
processLine_。processLine_在这两种情况下都是一样的,它做一些类似聚合的事情。我有另一种显示结果的方法。 -
@FrançoisAndrieux 不,我不会在
processLine_方法之外使用它们。所有代码不变 -
我们甚至看不到您描述的代码。尝试使用性能分析器。