[英]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()
一样快,但需要一些额外的代码...
出乎意料的是,使用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
只是具有非常有效的重新分配策略。
( 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.