关于iostream的效率问题
前言
经常有人说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的效率问题的更多相关文章
- Golang 效率初(粗)测
从接触 Golang 开始,断断续续已有差不多一年左右的时间了,都是业余自己学学看看,尚主要限于语法及语言特性,还没有用它写过实际的项目. 关于 Golang 的语法及语言特性,网上有很多资源可以学习 ...
- C++操作MySQL大量数据插入效率低下的解决方法
#include <iostream> #include <winsock2.h> #include <string> #include "mysql.h ...
- 测试lua的效率
这几天粗略的测试了一下lua的效率!首先声明这个测试很有针对性,大部分是针对游戏中的使用,而绝非lua的整体性效率(这个测试我不会),lua构建的上层逻辑中,大概使用的语句不太多,for,迭代,调用C ...
- include<stdio.h> 和include<iostream.h>的区别
stdio 是C标准库里面的函数库 对应的基本都是标准输入输出等等C语言常用库的定义iostream是C++标准库的头定义, 对应的基本上是C++的输入输出相关库定义开发C程序用Stdio, C++用 ...
- 基于OpenMP的矩阵乘法实现及效率提升分析
一. 矩阵乘法串行实现 例子选择两个1024*1024的矩阵相乘,根据矩阵乘法运算得到运算结果.其中,两个矩阵中的数为double类型,初值由随机数函数产生.代码如下: #include <i ...
- c++拼接字符串效率比较(+=、append、stringstream、sprintf)
转自:http://www.cnblogs.com/james6176/p/3222671.html c++拼接字符串效率比较(+=.append.stringstream.sprintf) 最近写的 ...
- iostream/fstream中的输入输出流指针的绑定,tie函数的使用。
为了兼容c语言的输入输出,c++里面采用tie将输入输出流经行绑定,所以cin/cout并不是独立的.当执行cin时,cout同时会被执行.反之亦然. by defalut,cin is tied ...
- Cin、Cout 加快效率方法
std::ios::sync_with_stdio(false); 在main 函数中加上这么一句话. 可以打消iostream的输入输出缓存,可以节省许多时间,使效率与scanf与printf相差无 ...
- CMap与hash_map效率对照
CMap与hash_map底层均採用hash stable实现,CMap是MFC提供的模板类.hash_map尽管眼下并未纳入C++标准模板类库,但差点儿每一个版本号的STL都提供了对应的实现.CMa ...
随机推荐
- C#的checked和unchecked
C#的 checked关键字用于对整型算术运算和转换显式启用溢出检查. 简单点说,我们在进行数值计算时,运算结果可能会超出该类型能表达的数值范围,因而结果溢出.而这个溢出如果是含有变量的表达式的话,编 ...
- 深入理解linux网络技术内幕读书笔记(十)--帧的接收
Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...
- HTML获取用户输入的几种玩法
input标签 input是一个自闭和标签,可以获得用户的输入 form标签 form标签是用来进行表单提交用的,它把用户的输入内容提交到服务器. 一个注册页面的例子 <!DOCTYPE htm ...
- 认识ptrace函数
认识ptrace函数 这是man对于ptrace这个系统调用的解释 http://man7.org/linux/man-pages/man2/ptrace.2.html #include <sy ...
- pptv web前端面试题答案
这是星期一考完试,答应星期三补上的,代码很简单,就不写注释了 //php快排 function quickSort(&$arr){ $arr_left=new array(); $ar ...
- [置顶] Android的IPC访问控制设计与实现
3.3.1 IPC钩子函数设计与实现 IPC Binder是Android最重要的进程间通信机制,因此,必须在此实施强制访问控制. 1. 修改secuirty.h 打开终端shell,输入指令“cd ...
- Linux下Weblogic域的创建过程
环境介绍:操作系统 :Redhat 5.5Weblogic :英文版 8.1.6 Weblogic安装目录 :/weblogic 一.域的建立执行下面语句进入weblogic的bin目录: cd /w ...
- mysql 建立加密连接
加密连接可提高数据的安全性,但会降低性能.要进行加密连接,必须满足以下要求: user权限表里要有相关的SSL数据列.如果安装的MySQL服务器是4.0.0版的,user权限表已包含相关的SSL数据列 ...
- Java基础知识强化67:基本类型包装类之Integer直接赋值的面试题
1. 面试题: Integer i = 1: i += 1: 做了哪些事情? (1)其中Integer i =1:做了自动装箱( 使用valueOf()方法,int ---> Integer ...
- Ajax&XMLHttpRequest
XMLHttpRequest 简单省力的方法 将文件编码成base64通过Ajax上传 HTML5学习之FileReader接口 HTML5学习之FileReader接口 通过Ajax方式上传文件,使 ...