在50:40的http://channel9.msdn.com/Events/GoingNative/2013/Writing-Quick-Code-in-Cpp-Quickly安德烈Alexandrescu开了一个玩笑,说istream是多么的不高效/慢。
我过去有一个问题,ostream很慢,fwrite明显更快(运行主循环一次会减少很多秒),但我从来不明白为什么,也不去研究它。
是什么让istream和ostream在C++中变慢?或者至少与同样满足需求的其他东西(如fread/fget、fwrite)相比慢。
5条答案
按热度按时间xyhw6mcr1#
事实上,IOStreams并不需要很慢!不过,这是一个以合理的方式实施它们的问题,使它们快速。大多数标准的C++库似乎都没有太多的注意力来实现IOStreams。很久以前,当我的CXXRT还在维护的时候,它大约和stdio一样快-当正确使用的时候!
但是,请注意,对于使用IOStreams布局的用户来说,几乎没有性能陷阱。以下指导原则适用于所有IOStream实现,尤其适用于那些为快速而定制的实现:
1.使用
std::cin
、std::cout
等时你需要调用std::sync_with_stdio(false)
!如果没有这个调用,任何标准流对象的使用都需要与C的标准流同步。当然,当使用std::sync_with_stdio(false)
时,假设您不会将std::cin
与stdin
、std::cout
与stdout
混合使用,等等。std::endl
,因为它要求对任何缓冲器进行许多不必要的刷新。同样,不要设置std::ios_base::unitbuf
或使用std::flush
。1.当创建自己的流缓冲区时(好吧,很少有用户这样做),请确保他们使用内部缓冲区!处理单个字符要经过多个条件和
virtual
函数,这使得它慢得可怕。ie3xauqp2#
[i]ostreams在设计上很慢的原因有几个:
*共享格式化状态:每个格式化输出操作必须检查可能先前已经由I/O操纵器改变的所有格式化状态。由于这个原因,iostreams本质上比类似
printf
的API慢(特别是使用格式字符串编译,如Rust或{fmt},避免解析开销),其中所有格式信息都是本地的。*不受控制地使用语言环境:所有的格式化都要经过一个低效的区域设置层,即使你不想这样,例如在编写JSON文件时。参见N4412: Shortcomings of iostreams。
*codegen无效:使用iostreams格式化消息通常由多个格式化函数调用组成,因为参数和I/O操纵器与消息的各个部分交错。例如,在中有三个这样的调用(godbolt
相比之下,在等价的
printf
调用中只有一个(godbolt):*额外的缓冲和同步。
sync_with_stdio(false)
可以禁用这一点,但代价是与其他I/O设施的互操作性较差。i2loujxw3#
也许这可以让你对你正在处理的事情有所了解:
运行这个,我得到这样的结果(使用MS VC ++):
这(与MinGW):
正如我们在结果中看到的,这并不是iostream绝对慢的问题。相反,这在很大程度上取决于您如何使用iostreams(在较小程度上也取决于
FILE *
)。在这些实现之间也有相当大的差异。尽管如此,每个版本(
fread
和istream::read
)的最快版本基本上是并列的。在VC ++中,getc
比istream::read
或istreambuf_iterator
慢很多。底线是:从iostreams获得良好的性能需要比使用
FILE *
多一点的注意--但这肯定是可能的。它还为您提供了更多的选择:当你不太关心速度时,你会发现它很方便,而且性能直接与你从C风格I/O中获得的最佳性能竞争,只需要一点额外的工作。q5iwbnjs4#
虽然这个问题很老了,但我很惊讶没有人提到iostream对象构造。
也就是说,每当创建STL
iostream
(和其他流变体)时,如果单步执行代码,构造函数将调用内部Init
函数。在这里,调用operator new
来创建一个新的locale
对象。同样的,也会被毁灭。这太可怕了,IMHO。这当然会导致对象构造/销毁速度变慢,因为内存在某个时候是使用系统锁来分配/释放的。
此外,一些STL流允许您指定
allocator
,那么为什么不使用指定的分配器创建locale
呢?在多线程环境中使用流,还可以想象每次构造新的流对象时调用
operator new
所造成的瓶颈。如果你问我的话,这是可怕的混乱,因为我现在发现自己!
cunj1qz15#
关于类似的主题,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