【问题标题】:How to get more performance when reading file读取文件时如何获得更高的性能
【发布时间】:2014-08-09 17:19:23
【问题描述】:

我的程序从站点下载文件(每 30 分钟通过 curl)。 (这些文件的大小可能达到 150 mb)

所以我认为从这些文件中获取数据可能效率低下。 (每 5 秒搜索一行)

这些文件可以有 ~10.000 行

要解析这个文件(值由“,”分隔),我使用正则表达式:

regex wzorzec("(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*)");

有 8 个值。

现在我必须把它推到向量:

allys.push_back({ std::stoi(std::string(wynik[1])), nick, tag, stoi(string(wynik[4])), stoi(string(wynik[5])), stoi(string(wynik[6])), stoi(string(wynik[7])), stoi(string(wynik[8])) });

我使用std::async 来执行此操作,但是对于 3 个文件 (~7 mb),处理器会跳转到 80%,并且操作大约需要 10 秒。我从 SSD 读取,所以这不是缓慢的 IO 故障。 我正在通过fstream每行读取数据线

如何提升这个操作? 也许我必须解析这些值,并将其推送到 SQL 中?

最好的问候

【问题讨论】:

  • 请参阅How to split a string in C++? 以获取解析行的正则表达式的替代方案
  • 正则表达式会导致你的处理器跳到 80% 不要为此使用正则表达式。
  • 你的正则表达式错了吗? '.*' 应该在大多数正则表达式解析引擎中贪婪地匹配,并且后面会包含逗号。
  • @C.R.那个正则表达式看起来不错,但是所有那些贪婪的量词都会使它变得非常低效。

标签: c++ regex multithreading


【解决方案1】:

避免使用regex 可能会提高性能,并使用类似于std::strtok 的内容,或者只需对数据中的逗号搜索进行硬编码。正则表达式的功能比您仅查找逗号所需的功能更多。接下来,如果您在为任何给定向量开始一系列push_back 之前使用vector::reserve,您将在重新分配和移动内存方面节省大量时间。如果您期望一个较大的向量,请预先为其预留空间。

这可能无法涵盖所有​​可用的性能想法,但我敢打赌你会看到改进。

【讨论】:

    【解决方案2】:

    您的问题很可能是正则表达式引入的额外开销,因为您使用了许多可变长度和贪婪匹配(正则表达式引擎将为匹配尝试不同的对齐方式以找到最大的匹配结果)。

    相反,您可能想尝试手动解析这些行。有许多不同的方法可以实现这一目标。这是一个快速而肮脏的例子(它不灵活,里面有很多重复的代码,但是还有很大的优化空间)。它应该解释基本思想:

    #include <iostream>
    #include <sstream>
    #include <cstdlib>
    
    const char *input = "1,Mario,Stuff,4,5,6,7,8";
    
    struct data {
        int id;
        std::string nick;
        std::string tag;
    } myData;
    
    int main(int argc, char **argv){
        char buffer[256];
        std::istringstream in(input);
    
        // Read an entry and convert/store it:
        in.get(buffer, 256, ','); // read
        myData.id = atoi(buffer); // convert and store
        // Skip the comma
        in.seekg(1, std::ios::cur);
    
        // Read the next entry and convert/store it:
        in.get(buffer, 256, ','); // read
        myData.nick = buffer; // store
        // Skip the comma
        in.seekg(1, std::ios::cur);
    
        // Read the next entry and convert/store it:
        in.get(buffer, 256, ','); // read
        myData.tag = buffer; // store
        // Skip the comma
        in.seekg(1, std::ios::cur);
    
        // Some test output
        std::cout << "id: " << myData.id << "\nnick: " << myData.nick << "\ntag: " << myData.tag << std::endl;
        return 0;
    }
    

    请注意,如果条目太长或太短(或以其他方式损坏),则不会进行任何错误处理。

    控制台输出:

    id: 1
    nick: Mario
    tag: Stuff
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多