Ref: 探寻C++最快的读取文件的方案

方法/平台/时间(秒) Linux gcc Windows mingw Windows VC2008
scanf 2.010 3.704 3.425
cin 6.380 64.003 19.208
cin取消同步 2.050 6.004 19.616
fread 0.290 0.241 0.304
read 0.290 0.398 不支持
mmap 0.250 不支持 不支持
Pascal read 2.160 4.668  

从上面可以看出几个问题

  1. Linux平台上运行程序普遍比Windows上快。
  2. Windows下VC编译的程序一般运行比MINGW(MINimal Gcc for Windows)快。
  3. VC对cin取消同步与否不敏感,前后效率相同。反过来MINGW则非常敏感,前后效率相差8倍。
  4. read本是linux系统函数,MINGW可能采用了某种模拟方式,read比fread更慢。
  5. Pascal程序运行速度实在令人不敢恭维。

不采用与采用read buffer的效果对比:(固态硬盘)

#if 1
g_bwtFile_idx = g_bwtFile_len;
do {
fread(&g_charbuf, , , g_bwtFile_fs_in);
g_Carr[(int)g_charbuf]++; } while((--g_bwtFile_idx) > );  // Time passed is: 2048 ms.
#else
do {
g_tmp_int = fread(&g_readBuf, , RBUF_SIZE, g_bwtFile_fs_in);
for(g_index_for = ; g_index_for < g_tmp_int; g_index_for++)
{
g_Carr[ (int)g_readBuf[g_index_for] ]++;
}
}while(g_tmp_int < g_readBuf);  // Time passed is: 79 ms.
#endif

Ref: Which is fastest: read, fread, ifstream or mmap?

method  millions of int. per s 
C read 70
C fread 124
C++ ifstream 124
mmap 125

简单的总结就是:
1. lseek 函数本身不会扩展文件的大小.
2. lseek 允许文件的偏移值超过文件的末端,如果下一次在这个偏移点写入数据,那么在偏移之前的文件末端与偏移点之间的数据将会自动填充为0。


计时方式: 同步与异步write的效率比较

    int ticks;
clock_t clockStart, clockEnd;
struct tms tmsStart, tmsEnd;
float userTime, sysTime, clockTime; printf("%-8s\t %-8s\t %-8s\t %-8s\t %-8s\t\n", "BUFFSIZE", "USER CPU", "SYSTEM CPU", "CLOCK CPU", "LOOP COUNT"); ticks = sysconf(_SC_CLK_TCK); for (;;) {
clockStart = times(&tmsStart); // ... clockEnd = times(&tmsEnd); userTime = (float)(tmsEnd.tms_utime - tmsStart.tms_utime)/ticks;
sysTime = (float)(tmsEnd.tms_stime - tmsStart.tms_stime)/ticks;
clockTime = (float)(clockEnd - clockStart)/ticks;
printf("%8d\t %8.2f\t %8.2f\t %8.2f\t %8d\n", buffSize, userTime, sysTime, clockTime, loopCount);
}

传参效率

对于内建的int char short long float等4字节或以下的数据类型而言

  实际上传递时也只需要传递1-4个字节,而使用指针传递时在32位cpu中传递的是32位的指针,4个字节,都是一条指令,这种情况下值传递和指针传递的效率是一样的,

  而传递double long long等8字节的数据时,

  •   在32位cpu中,其传值效率比传递指针要慢,因为8个字节需要2次取完。
  •   在64位的cpu上,传值和传址的效率是一样的。

  再说引用传递,这个要看编译器具体实现,

  引用传递最显然的实现方式是使用指针,这种情况下与指针的效率是一样的,

  而有些情况下编译器是可以优化的,采用直接寻址的方式,这种情况下,效率比传值调用和传址调用都要快,与上面说的采用全局变量方式传递的效率相当。

自定义的数据类型,class struct定义的数据类型。

  这些数据类型在进行传值调用时生成临时对象会执行构造函数,

  而且当临时对象销毁时会执行析构函数,如果构造函数和析构函数执行的任务比较多,或者传递的对象尺寸比较大,那么传值调用的消耗就比较大。

  这种情况下,采用传址调用和采用传引用调用的效率大多数下相当,正如上面所说,某些情况下引用传递可能被优化,总体效率稍高于传址调用。

执行效率

这里所说的执行效率,是指在被调用的函数体内执行时的效率。

  •   传值调用时,当值被传到函数体内,临时对象生成以后,所有的执行任务都是通过直接寻址的方式执行的,
  •   指针和大多数情况下的引用则是以间接寻址的方式执行的,所以实际的执行效率会比传值调用要低。

  如果函数体内对参数传过来的变量进行操作比较频繁,执行总次数又多的情况下,传址调用和大多数情况下的引用参数传递会造成比较明显的执行效率损失。

Thus,

综上所述,具体的执行效率要结合实际情况,通过比较传递过程的资源消耗执行函数体消耗之和来选择哪种情况比较合适。

而就引用传递和指针传递的效率上比,引用传递的效率始终不低于指针传递,所以从这种意义上讲,在c++中进行参数传递时优先使用引用传递而不是指针

如果没有必要,就使用值传递和引用传递,最好不用指针传递,更好地利用编译器的类型检查,使得我们有更少的出错机会,以增加代码的健壮性。

谨记:

  1. 内建的数据类型优先使用值传递,
  2. 自定义的数据类型,特别是传递较大的对象,请使用引用传递。

[Optimisation] Read & Write file on Hard Disk的更多相关文章

  1. Unix:关于一个file在file system和disk中占用空间

    參考文献: Harley Hahns:Guide to Unix and Linux. Chap 24 -->首先要有的关键概念:the amount of "disk space&q ...

  2. [Code::Blocks] Install wxWidgets & openCV

    The open source, cross platform, free C++ IDE. Code::Blocks is a free C++ IDE built to meet the most ...

  3. 本人SW知识体系导航 - Programming menu

    将感悟心得记于此,重启程序员模式. js, py, c++, java, php 融汇之全栈系列 [Full-stack] 快速上手开发 - React [Full-stack] 状态管理技巧 - R ...

  4. Java NIO read/write file through FileChannel

    referee:  Java NIO FileChannel A java nio FileChannel is an channel that is connected to a file. Usi ...

  5. 理解LGWR,Log File Sync Waits以及Commit的性能问题[转]

    理解LGWR,Log File Sync Waits以及Commit的性能问题 一.概要: 1.  Commit和log filesync的工作机制 2.  为什么log file wait太久 3. ...

  6. File I/O

    File I/O Introduction     We'll start our discussion of the UNIX System by describing the functions ...

  7. InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法

    InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法 140628  8:10:48 [Note] Plugi ...

  8. File System Design Case Studies

    SRC=http://www.cs.rutgers.edu/~pxk/416/notes/13-fs-studies.html Paul Krzyzanowski April 24, 2014 Int ...

  9. Extension of write anywhere file system layout

    A file system layout apportions an underlying physical volume into one or more virtual volumes (vvol ...

随机推荐

  1. 一段用c#操作datatable的代码

    using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; usin ...

  2. UITransitionView and UILayoutContainerView

    What is UITransitionView? What is UILayoutContainerView? Will I get in trouble for adding subviews t ...

  3. Python打包方法——Pyinstaller

    Python版本:Python3.5.2 一.安装Pyinstaller 1.安装pywin32 下载安装文件:查找到跟自己适用的python版本及window系统版本匹配的pywin32,下载后安装 ...

  4. AS 自定义 Gradle plugin 插件 案例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  5. android学习笔记(8)linearlayout与android:layout_weight学习

    一,linearlayout 线性布局,布局文件里设置多个linearlayout来达到总体线性布局的风格. android:gravity="right"对齐方式,居右对齐,gr ...

  6. JAVA和C#检测IP地址段是否交叉和获取地址段IP列表的方法

    一.说明 我们经常编程时,需要对一个DIDR地段计算其可用IP地址,或者验证某个IP是否被包含在一个地址段中. 二.工具 1.Java 可以使用 cidr-ip-trie库解决. https://gi ...

  7. ng-repeat不添加容器标签

    如UL中的循环, 我们不期望添加额外的div之类的容器标签, 使用ng-repeat-start和ng-repeat-end可以实现 <li class="item item-icon ...

  8. dubbo服务启动的方式

    dubbo服务启动的方式: 1.dubbo自带的脚本, 2.直接用main方法启动dubbo的spring容器,参见dubbo-test里的各个例子 3.dubbo的spring boot start ...

  9. Mysql 8 常用命令测试

    1.创建数据库,帐号及授权 create database testdb; CREATE USER 'rusking'@'%' IDENTIFIED BY '12345678'; CREATE USE ...

  10. PHP 扩展开发之Zephir

    最近对代码进行性能分析后,发现两个耗时的地方:自动加载文件数太多:参数验证函数调用超过1000次.这也是许多php语言框架面临的问题,所以发展出来诸如Yaf,Swoole,Phalcon这些C语言扩展 ...