C++;iostreams的标准指令性能较差,还是我只是在处理较差的实现? 每次我提到C++标准库IOFROM的慢速性能时,我都会遇到一种不信任的浪潮。然而,我的探查器结果显示,在iostream库代码(完整的编译器优化)上花费了大量时间,从iostream切换到特定于操作系统的I/oapi和自定义缓冲区管理确实带来了一个数量级的改进 < C++标准库做什么额外的工作,是标准要求的,在实践中有用吗?或者有些编译器提供的iostreams实现与手动缓冲区管理具有竞争力吗 基准

C++;iostreams的标准指令性能较差,还是我只是在处理较差的实现? 每次我提到C++标准库IOFROM的慢速性能时,我都会遇到一种不信任的浪潮。然而,我的探查器结果显示,在iostream库代码(完整的编译器优化)上花费了大量时间,从iostream切换到特定于操作系统的I/oapi和自定义缓冲区管理确实带来了一个数量级的改进 < C++标准库做什么额外的工作,是标准要求的,在实践中有用吗?或者有些编译器提供的iostreams实现与手动缓冲区管理具有竞争力吗 基准,c++,performance,iostream,C++,Performance,Iostream,为了让事情进展顺利,我编写了两个简短的程序来练习iostreams内部缓冲: 将二进制数据放入ostringstream 将二进制数据放入char[]缓冲区 使用back\u插入器将二进制数据放入向量中 新建:向量简单迭代器 NEW:将二进制数据直接放入stringbuf 新建:向量简单迭代器加边界检查 请注意,ostringstream和stringbuf版本运行的迭代次数较少,因为它们的速度要慢得多 在ideone上,ostringstream比std:copy+back\u inser

为了让事情进展顺利,我编写了两个简短的程序来练习iostreams内部缓冲:

  • 将二进制数据放入
    ostringstream
  • 将二进制数据放入
    char[]
    缓冲区
  • 使用
    back\u插入器将二进制数据放入
    向量中
  • 新建
    向量
    简单迭代器
  • NEW:将二进制数据直接放入
    stringbuf
  • 新建
    向量
    简单迭代器加边界检查
请注意,
ostringstream
stringbuf
版本运行的迭代次数较少,因为它们的速度要慢得多

在ideone上,
ostringstream
std:copy
+
back\u inserter
+
std::vector
慢约3倍,比
memcpy
慢约15倍进入原始缓冲区。当我将我的实际应用程序切换到自定义缓冲时,这感觉与评测前后一致

这些都是内存缓冲区,所以IO流的慢不能归咎于慢磁盘I/O、过多刷新、与STDIO同步,或者人们用来解释C++标准库IOSWATE的慢速的任何其他事情。 <> P> >在其他系统上查看基准和对常用实现(例如GCC的LBC++、Visual C++、英特尔C++)和标准中的开销有多大的评论是很好的。 这项测试的基本原理 许多人正确地指出iostream更常用于格式化输出。然而,它们也是由C++标准提供的唯一的二进制文件访问的现代API。但是,对内部缓冲进行性能测试的真正原因适用于典型的格式化I/O:如果iostreams不能向磁盘控制器提供原始数据,那么当它们也负责格式化时,它们又如何能够跟上呢

基准时间 所有这些都是外部(
k
)循环的每次迭代

在ideone上(gcc-4.3.4,未知操作系统和硬件):

  • ostringstream
    :53毫秒
  • stringbuf
    :27毫秒
  • 向量
    反向插入器
    :17.6毫秒
  • 向量
    使用普通迭代器:10.6 ms
  • vector
    迭代器和边界检查:11.4毫秒
  • char[]
    :3.7毫秒
<我的笔记本电脑(Visual C++ 2010 x86,<代码> Cl/ox/eSCC < /COD>,Windows 7最终64位,英特尔核心I7,8 GB RAM):

  • ostringstream
    :73.4毫秒,71.6毫秒
  • stringbuf
    :21.7毫秒,21.3毫秒
  • 向量
    反向插入器
    :34.6毫秒,34.4毫秒
  • 向量
    使用普通迭代器:1.10毫秒,1.04毫秒
  • vector
    迭代器和边界检查:1.11毫秒、0.87毫秒、1.12毫秒、0.89毫秒、1.02毫秒、1.14毫秒
  • char[]
    :1.48毫秒,1.57毫秒

Visual C++ 2010 x86,配置文件优化优化>代码> Cl/ox/EHSC/GL/C<<代码>,<代码>链接/LTCG:PGI,运行,<代码>链接/LTCG:PGO < /C> >,测量:

  • ostringstream
    :61.2毫秒,60.5毫秒
  • 向量
    使用普通迭代器:1.04毫秒,1.03毫秒
同样的笔记本电脑,同样的操作系统,使用cygwin gcc 4.3.4
g++-O3

  • ostringstream
    :62.7毫秒,60.5毫秒
  • stringbuf
    :44.4毫秒,44.5毫秒
  • 向量
    反向插入器
    :13.5毫秒,13.6毫秒
  • 向量
    使用普通迭代器:4.1毫秒,3.9毫秒
  • vector
    迭代器和边界检查:4.0毫秒,4.0毫秒
  • char[]
    :3.57毫秒,3.75毫秒

同一台笔记本电脑,Visual C++ 2008 SP1,<代码> Cl/ox/EHSC >:

  • ostringstream
    :88.7毫秒,87.6毫秒
  • stringbuf
    :23.3毫秒,23.4毫秒
  • 向量
    反向插入器
    :26.1毫秒,24.5毫秒
  • vector
    带普通迭代器:3.13毫秒,2.48毫秒
  • vector
    迭代器和边界检查:2.97毫秒,2.53毫秒
  • char[]
    :1.52毫秒,1.25毫秒

同一台笔记本电脑,Visual C++ 2010位64位编译器:

  • ostringstream
    :48.6毫秒,45.0毫秒
  • stringbuf
    :16.2毫秒,16.0毫秒
  • 向量
    反向插入器
    :26.3毫秒,26.5毫秒
  • 向量
    使用普通迭代器:0.87毫秒,0.89毫秒
  • vector
    迭代器和边界检查:0.99毫秒,0.99毫秒
  • char[]
    :1.25毫秒,1.24毫秒
编辑:全部运行两次以查看结果的一致性。我觉得很稳定

注意:在我的笔记本电脑上,因为我可以比ideone允许的更多的CPU时间,所以我将所有方法的迭代次数设置为1000。这意味着仅在第一次传递时发生的
ostringstream
vector
重新分配对最终结果的影响应该很小

EDIT:Oops,在
向量中发现了一个bug
——使用普通迭代器时,迭代器没有升级,因此缓存命中过多。我在想