前言
    经常有人说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. C#的checked和unchecked

    C#的 checked关键字用于对整型算术运算和转换显式启用溢出检查. 简单点说,我们在进行数值计算时,运算结果可能会超出该类型能表达的数值范围,因而结果溢出.而这个溢出如果是含有变量的表达式的话,编 ...

  2. 深入理解linux网络技术内幕读书笔记(十)--帧的接收

    Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...

  3. HTML获取用户输入的几种玩法

    input标签 input是一个自闭和标签,可以获得用户的输入 form标签 form标签是用来进行表单提交用的,它把用户的输入内容提交到服务器. 一个注册页面的例子 <!DOCTYPE htm ...

  4. 认识ptrace函数

    认识ptrace函数 这是man对于ptrace这个系统调用的解释 http://man7.org/linux/man-pages/man2/ptrace.2.html #include <sy ...

  5. pptv web前端面试题答案

    这是星期一考完试,答应星期三补上的,代码很简单,就不写注释了 //php快排 function quickSort(&$arr){   $arr_left=new array();   $ar ...

  6. [置顶] Android的IPC访问控制设计与实现

    3.3.1 IPC钩子函数设计与实现 IPC Binder是Android最重要的进程间通信机制,因此,必须在此实施强制访问控制. 1. 修改secuirty.h 打开终端shell,输入指令“cd ...

  7. Linux下Weblogic域的创建过程

    环境介绍:操作系统 :Redhat 5.5Weblogic :英文版 8.1.6 Weblogic安装目录 :/weblogic 一.域的建立执行下面语句进入weblogic的bin目录: cd /w ...

  8. mysql 建立加密连接

    加密连接可提高数据的安全性,但会降低性能.要进行加密连接,必须满足以下要求: user权限表里要有相关的SSL数据列.如果安装的MySQL服务器是4.0.0版的,user权限表已包含相关的SSL数据列 ...

  9. Java基础知识强化67:基本类型包装类之Integer直接赋值的面试题

    1. 面试题: Integer  i = 1: i += 1: 做了哪些事情? (1)其中Integer i =1:做了自动装箱( 使用valueOf()方法,int ---> Integer ...

  10. Ajax&XMLHttpRequest

    XMLHttpRequest 简单省力的方法 将文件编码成base64通过Ajax上传 HTML5学习之FileReader接口 HTML5学习之FileReader接口 通过Ajax方式上传文件,使 ...