前言
    经常有人说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. .net连接oracle(无客户端)

    使用DDTek.Oracle.dll可以在没有安装oracle客户端的情况下连接远程的oracle. string _conString = "Host=192.168.1.1;Port=1 ...

  2. 安卓学习之路 -- JAVA多线程下载

    代码没有优化,暂时先实现结果 package download; import java.io.File; import java.io.InputStream; import java.io.Ran ...

  3. hdu 4841 圆桌问题(STL vector)

    Problem Description 圆桌上围坐着2n个人.其中n个人是好人,另外n个人是坏人.如果从第一个人开始数数,数到第m个人,则立即处死该人:然后从被处死的人之后开始数数,再将数到的第m个人 ...

  4. Python学习日志(六)

    字符串的方法及注释 字符串转义字符含义 字符串格式化符号含义 eg:'a'的ASCii码是97 格式化操作符辅助指令 format()字符串格式化方法 字符串的格式化是指统一字符串格式 format( ...

  5. 关于在centos7上安装vmtools的各种报错的问题处理

    基本上如果安装vmtools时报错的错,首先记录一下报错信息 例如,本次遇见的就是 /tmp/modconfig-8mD7iy/vmhgfs-only/page.c:1625:23: 错误:提供给函数 ...

  6. Python进阶(面向对象编程基础)(四)

    1.方法也是属性 我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象: class Person(object): def __init__(self, name, score) ...

  7. 导航条上UIBarButtonItem的更改方法(使用initWithCustomView:btn)

    UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:self.newMe ...

  8. 2.x最终照着教程,成功使用OpenGL ES 绘制纹理贴图,添加了灰度图

    在之前成功绘制变色的几何图形之后,今天利用Openg ES的可编程管线绘制出第一张纹理. 学校时候不知道OpenGL的重要性,怕晦涩的语法.没有跟老师学习OpenGL的环境配置,现在仅仅能利用coco ...

  9. C++ 用libcurl库进行http通讯网络编程[转]

    http://www.cnblogs.com/moodlxs/archive/2012/10/15/2724318.html 目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.cur ...

  10. 论js闭包的重要性

    很久没写博客了,今天发现了一个很有意思的问题,写下来分享一下 话不多说,贴前端代码: <script type="text/javascript" src="js/ ...