前言
    经常有人说iostream的速度慢,IO流比stdio的慢多了。但是有人测试过的,iostream的速度是超过stdio的。

测试结果

/* C */
#include <stdio.h>

int main()
{
    FILE* stream;
    size_t num;
    size_t sum = 0;
    size_t i = 0;

stream = fopen("random.data", "r");
    while(fscanf(stream, "%u", &num) != EOF)
    {
        sum += num;
    }
    fclose(stream);

printf("%u\n", sum);
    return 0;
}

/* C++ */
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream stream("random.data");
    size_t num;
    size_t sum = 0;

while(stream >> num)
    {
        sum += num;
    }
    cout << sum << endl;
    return 0;
}

random.data中为100000个0-32767的随机数

C版本平均用时0.64s,C++平均用时0.58s

于是又把这陈芝麻烂谷子事拿出来研究。单步VC10/11(用后者是因为新版加入了chrono方便计时),cout输出一段字符串的调用顺序如下:

 

operator<< => sputn => xsputn => overflow => _Fputc => fputc
cout封装了fputc一个字符一个字符的输出,而Win下默认不给stdout开buffer,于是造成cout输出字符串极度缓慢,杯具出现了
想起线程安全性问题。cout虽然线程安全(原文:http://msdn.microsoft.com/en-us/library/c9ceah3b.aspx),但是输出的字符是混在一起的,我猜想也是cout封装fputc而在fputc里加锁的原因。

看printf()的源码:
    va_start(arglist, format);

_lock_str2(1, stdout);
    __try {
// int _stbuf(stream) - set temp buffer on stdout, stdprn, stderr
        buffing = _stbuf(stdout);

retval = _output_l(stdout,format,NULL,arglist);

// void _ftbuf(flag, stream) - take temp buffering off a stream
        _ftbuf(buffing, stdout);

}
    __finally {
        _unlock_str2(1, stdout);
    }
首先将stdout整体加锁,然后给stdout开了一个临时buffer,输出后再刷新,显然要比cout快得多。

测试用了fstream,文件指针在win下是默认开buffer的,于是给cout手动开buffer,前后测试结果如下:

未开buffer:

 

开了buffer:

 

可以看到未开buffer时cout的用时比printf慢数十倍,开buffer后的用时与printf已经十分接近(cout绑定stdout,给cout开buffer就等于给printf开buffer),造成的差异应该是每个字符分别加锁的缘故。另外printf用%s输出比直接输出快,大概是因为直接输出的话解析格式字符串时每个字符都要判断format[n]=='%'

这是g++ MinGW-w64的测试结果:
未开buffer:

 

开了buffer:

 

stdlibc++使用了不同的封装方式,未开buffer时两者速度已经较为接近,开buffer后已经超过用printf直接输出。

关于g++和VC的速度比较,除了原生64位以外,CRT也有差距,毕竟VC是微软自己的东西
注:mingw的cout.rdbuf()->pubsetbuf似乎有问题,改用setvbuf

附虚拟机下Fedora 16(g++ 4.6.2)测试结果(linux默认给stdout开buffer)

 

TIP:
   关于cout输出慢,可能是buffer刷新的问题 把endl换成'\n'就会快上许多了。

关于iostream的效率问题的更多相关文章

  1. Golang 效率初(粗)测

    从接触 Golang 开始,断断续续已有差不多一年左右的时间了,都是业余自己学学看看,尚主要限于语法及语言特性,还没有用它写过实际的项目. 关于 Golang 的语法及语言特性,网上有很多资源可以学习 ...

  2. C++操作MySQL大量数据插入效率低下的解决方法

    #include <iostream> #include <winsock2.h> #include <string> #include "mysql.h ...

  3. 测试lua的效率

    这几天粗略的测试了一下lua的效率!首先声明这个测试很有针对性,大部分是针对游戏中的使用,而绝非lua的整体性效率(这个测试我不会),lua构建的上层逻辑中,大概使用的语句不太多,for,迭代,调用C ...

  4. include<stdio.h> 和include<iostream.h>的区别

    stdio 是C标准库里面的函数库 对应的基本都是标准输入输出等等C语言常用库的定义iostream是C++标准库的头定义, 对应的基本上是C++的输入输出相关库定义开发C程序用Stdio, C++用 ...

  5. 基于OpenMP的矩阵乘法实现及效率提升分析

    一.  矩阵乘法串行实现 例子选择两个1024*1024的矩阵相乘,根据矩阵乘法运算得到运算结果.其中,两个矩阵中的数为double类型,初值由随机数函数产生.代码如下: #include <i ...

  6. c++拼接字符串效率比较(+=、append、stringstream、sprintf)

    转自:http://www.cnblogs.com/james6176/p/3222671.html c++拼接字符串效率比较(+=.append.stringstream.sprintf) 最近写的 ...

  7. iostream/fstream中的输入输出流指针的绑定,tie函数的使用。

      为了兼容c语言的输入输出,c++里面采用tie将输入输出流经行绑定,所以cin/cout并不是独立的.当执行cin时,cout同时会被执行.反之亦然. by defalut,cin is tied ...

  8. Cin、Cout 加快效率方法

    std::ios::sync_with_stdio(false); 在main 函数中加上这么一句话. 可以打消iostream的输入输出缓存,可以节省许多时间,使效率与scanf与printf相差无 ...

  9. CMap与hash_map效率对照

    CMap与hash_map底层均採用hash stable实现,CMap是MFC提供的模板类.hash_map尽管眼下并未纳入C++标准模板类库,但差点儿每一个版本号的STL都提供了对应的实现.CMa ...

随机推荐

  1. velocity自定义动画

         话说好久没有写博客了,零星的整理了一些东西,没有形成系统,所以也没有在这里记录.        废话不多说了,进入今天的正题.不知道大家是否记得之前写过的一篇文章<制作炫酷的专题页面& ...

  2. ik分词

    Ik中文分词的引入 ik版本号:IK Analyzer 2012FF_hf1 下载地址: http://code.google.com/p/ik-analyzer/downloads/list 解压 ...

  3. 日期函数(SqlServer)

    1.常用日期方法(下面的GetDate() = '2006-11-08 13:37:56.233') (1)DATENAME ( datepart ,date ) 返回表示指定日期的指定日期部分的字符 ...

  4. iOS--tableview分组

    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ ; } -(NSInteger)tableView:(UITable ...

  5. WebMagic的设计参考了业界最优秀的爬虫Scrapy

    http://webmagic.io/docs/zh/posts/ch1-overview/thinking.html https://github.com/psvehla/liferay-sprin ...

  6. Guzzle php resetful webservice farmework

    Guzzle is a PHP HTTP client that makes it easy to work with HTTP/1.1 and takes the pain out of consu ...

  7. UVAlive 6131 dp+斜率优化

    这道题和06年论文<从一类单调性问题看算法的优化>第一道例题很相似. 题意:给出n个矿的重量和位置,这些矿石只能从上往下运送,现在要在这些地方建造m个heap,要使得,sigma距离*重量 ...

  8. C++类的const成员函数、默认的构造函数、复制形参调用函数(转)

    C++类的const成员函数 double Sales_item::avg_price() const { } const关键字表明这是一个const成员函数,它不可以修改Sales_item类的成员 ...

  9. Vss服务端用户存在,但客户端登陆不进去

    打开客户端Vss提示“Cannot find SS.INI file for user userName”,这个错误是找不到用户userName的SS.INI文件. 解决办法 在服务器上找到Vss共享 ...

  10. AlwaysON同步过程

    <SQL Server 2012实施与管理实战指南>中指AlwaysON同步过程如下: 任何一个SQL Server里都有个叫Log Writer的线程,当任何一个SQL用户提交一个数据修 ...