繁体   English   中英

用C ++将stdin的内容读入字符串或向量的最快方法

[英]Fastest way in c++ to read contents of stdin into a string or vector

许多stackoverflow答案都涉及如何从磁盘中插入文件,您可以在其中根据文件大小预分配内存。

但是,在stdin中进行提取的最快方法是什么(例如,将大文件通过管道传输到程序中)?

如果这是最快的解决方案,我很乐意将其插入向量(以后可以随时将其转换为std :: string)。

将未格式化的数据读入内存的最快方法是使用未格式化的读取例程。 例如,fstream :: read()。 没有什么能打败它。

谨防! 有些人声称,通过使用操作系统级别的例程(如read()),您将看到性能的提高。 如果尝试这种方法,将会导致极大的性能下降。

编辑。 以上陈述的一些解释。 降级的原因是内核调用。 每次读取都是对内核的调用,因此,除非您精确地读取最佳数据缓冲区的大小,否则将增加对内核的调用或减少对最佳读取的调用。 尽管您可以通过实验确定最佳读取大小,但C运行时已经为您完成了这项工作。 fread()和无格式的流读取已经进行了优化,因此无论您的读取块有多大,都保证以最佳方式调用内核。

循环读取固定大小的缓冲区

令我惊讶的是,使用clang和gcc的老式,几乎类似于c的代码似乎是最快的:

{
    vector<char> cin_str;
    // 64k buffer seems sufficient
    std::streamsize buffer_sz = 65536;
    vector<char> buffer(buffer_sz);
    cin_str.reserve(buffer_sz);

    auto rdbuf = cin.rdbuf();
    while (auto cnt_char = rdbuf->sgetn(buffer.data(), buffer_sz))
        cin_str.insert(cin_str.end(), buffer.data(), buffer.data() + cnt_char);
}

使用istream::read()istream::gcount()一样快,但需要一些额外的代码...

C ++迭代器

出乎意料的是,使用istreambuf_iterator (用于无格式输入的迭代器)的速度要慢得多:即使关闭与stdio的同步后,对于某些测试文件,该速度也要> 3倍。

{
    std::ios_base::sync_with_stdio(false) ;
    vector<char> cin_str;
    //              64k
    std::streamsize buffer_sz = 65536;
    cin_str.reserve(buffer_sz);

    std::istreambuf_iterator<char> iit (std::cin.rdbuf()); // stdin iterator
    std::istreambuf_iterator<char> eos;                    // end-of-range iterator
    std::copy(iit, eos, std::back_inserter(cin_str));
    return cin_str;
}

即使在为vector缓冲区保留了空间(而不只是分配给它)之后,也是如此。

另一个惊喜是,即使缓冲区大小非常适中(64 kb),也能看到(接近)最大速度。 vector只是具有非常有效的重新分配策略。

附录:

Google-ing找到此博客文章

http://insanecoding.blogspot.in/2011/11/reading-in-entire-file-at-once-in-c.html )从2011年开始,这似乎表明这种方法的运行速度是最快的在c ++中(在gcc / clang中),切换到cstdio不会带来更多收益(但显然会使代码更丑陋!)。

避免复制

@BenVoigt指出,如果我们明智地预分配必要的空间,则可以通过sgetn() / istream::read()将读取的数据放置在适当的位置:

{
    std::ios_base::sync_with_stdio(false) ;
    //              64k
    std::streamsize buffer_sz = 65536;
    vector<char> cin_str(buffer_sz);
    std::streamsize cin_str_data_end = 0U;

    auto rdbuf = cin.rdbuf();
    while (auto cnt_char = rdbuf->sgetn(cin_str_data_end + cin_str.data(), buffer_sz))
    {
        cin_str_data_end += cnt_char;
        cin_str.resize(cin_str_data_end + buffer_sz);
    }
    cin_str.resize(cin_str_data_end);
    return cin_str;
}

在测试中,这可能导致进一步的加速,原因可能是此代码主要受以下因素的影响:1)i / o 2)系统调用开销3)矢量内存分配

有更快的方法吗? 提升内存映射文件?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM