Why is istream/ostream slow
在http://channel9.msdn.com/events/goingnative/2013/writing-quick-code-in-cpp-quickly Andrei Alexandrescu的50:40,他开玩笑说Istream有多不高效/慢。
我以前遇到过这样一个问题:Ostream速度慢,fwrite速度快得多(运行一次主循环时缩短了很多秒),但我不明白原因,也不去研究它。
是什么使得ISTRAM和OFFASE在C++中缓慢?或者至少比其他同样能满足需求的东西(如fread/fget、fwrite)要慢。
实际上,iostreams不必慢!不过,这是一个以合理的方式实现它们以使其快速的问题。大多数标准C++库似乎不太重视实现IoFiels.很久以前,当我的cxrt还在维护的时候,它和stdio一样快——正确使用的时候!
但是,请注意,对于使用iostreams部署的用户,性能陷阱很少。以下指导原则适用于所有iostream实现,尤其适用于那些为快速而定制的实现:
也许这可以让你对你正在处理的事情有所了解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #include <stdio.h> #include <iomanip> #include <iostream> #include <iterator> #include <fstream> #include <time.h> #include <string> #include unsigned count1(FILE *infile, char c) { int ch; unsigned count = 0; while (EOF != (ch=getc(infile))) if (ch == c) ++count; return count; } unsigned int count2(FILE *infile, char c) { static char buffer[8192]; int size; unsigned int count = 0; while (0 < (size = fread(buffer, 1, sizeof(buffer), infile))) for (int i=0; i<size; i++) if (buffer[i] == c) ++count; return count; } unsigned count3(std::istream &infile, char c) { return std::count(std::istreambuf_iterator<char>(infile), std::istreambuf_iterator<char>(), c); } unsigned count4(std::istream &infile, char c) { return std::count(std::istream_iterator<char>(infile), std::istream_iterator<char>(), c); } unsigned int count5(std::istream &infile, char c) { static char buffer[8192]; unsigned int count = 0; while (infile.read(buffer, sizeof(buffer))) count += std::count(buffer, buffer+infile.gcount(), c); count += std::count(buffer, buffer+infile.gcount(), c); return count; } unsigned count6(std::istream &infile, char c) { unsigned int count = 0; char ch; while (infile >> ch) if (ch == c) ++count; return count; } template <class F, class T> void timer(F f, T &t, std::string const &title) { unsigned count; clock_t start = clock(); count = f(t, 'N'); clock_t stop = clock(); std::cout << std::left << std::setw(30) << title <<"\tCount:" << count; std::cout <<"\tTime:" << double(stop-start)/CLOCKS_PER_SEC <<" "; } int main() { char const *name ="equivs2.txt"; FILE *infile=fopen(name,"r"); timer(count1, infile,"ignore"); rewind(infile); timer(count1, infile,"using getc"); rewind(infile); timer(count2, infile,"using fread"); fclose(infile); std::ifstream in2(name); timer(count3, in2,"ignore"); in2.clear(); in2.seekg(0); timer(count3, in2,"using streambuf iterators"); in2.clear(); in2.seekg(0); timer(count4, in2,"using stream iterators"); in2.clear(); in2.seekg(0); timer(count5, in2,"using istream::read"); in2.clear(); in2.seekg(0); timer(count6, in2,"using operator>>"); return 0; } |
运行这个,我得到这样的结果(使用MS VC++):
1 2 3 4 5 6 7 8 | ignore Count: 1300 Time: 0.309 using getc Count: 1300 Time: 0.308 using fread Count: 1300 Time: 0.028 ignore Count: 1300 Time: 0.091 using streambuf iterators Count: 1300 Time: 0.091 using stream iterators Count: 1300 Time: 0.613 using istream::read Count: 1300 Time: 0.028 using operator>> Count: 1300 Time: 0.619 |
这个(和明格一起):
1 2 3 4 5 6 7 8 | ignore Count: 1300 Time: 0.052 using getc Count: 1300 Time: 0.044 using fread Count: 1300 Time: 0.036 ignore Count: 1300 Time: 0.068 using streambuf iterators Count: 1300 Time: 0.068 using stream iterators Count: 1300 Time: 0.131 using istream::read Count: 1300 Time: 0.037 using operator>> Count: 1300 Time: 0.121 |
正如我们在结果中看到的那样,IOstreams绝对缓慢并不是问题。更确切地说,很大程度上取决于您如何使用iostreams(在较小程度上也取决于
尽管如此,每个版本的最快版本(
底线:从iostreams获得良好的性能需要比使用
虽然这个问题很古老,但我很惊讶没有人提到iostream对象构造。
也就是说,每当您创建一个stl
这太可怕了,imho。当然,这会导致对象构造/破坏的速度变慢,因为在某些时候,内存是使用系统锁分配/释放的。
此外,一些STL流允许您指定一个
在多线程环境中使用流,还可以想象每次构造新的流对象时调用
如果你问我的话,那真是一团糟,因为我现在正发现自己呢!
在类似的主题中,stl说:"可以调用setvbuf()在stdout上启用缓冲。"
https://web.archive.org/web/20170329163751/https://connect.microsoft.com/VisualStudio/Feedback/Details/642876/std-wcout-is-ten-times-slower-than-wprintf-performance-bug-in-c-library