作为这个讨论的开始,这里有几个如何加速I/O的基本规则:

1. 避免访问磁盘

2. 避免访问底层的操作系统

3. 避免方法调用

4. 避免个别的处理字节和字符

很明显这些规则不能在所有的问题上避免,因为如果能够的话就没有实际的I/O被执行。考虑下面的计算文件中的新行符('\n')的三部分范例。

方法1: read方法

第一个方法简单的使用FileInputStream的read方法:

import java.io.*;

public class intro1 {

public static void main(String args[]) {

if (args.length != 1) {

System.err.println("missing filename");

System.exit(1);

}

try {

FileInputStream fis = new FileInputStream(args[0]);

int cnt = 0;

int b;

while ((b = fis.read()) != -1) {

if (b == '\n')

cnt++;

}

fis.close();

System.out.println(cnt);

} catch (IOException e) {

System.err.println(e);

}

}

}然而这个方法触发了大量的底层运行时系统调用--FileInputStream.read--返回文件的下一个字节的本机方法。

方法 2: 使用大缓冲区

第二种方法使用大缓冲区避免了上面的问题:

import java.io.*;

public class intro2 {

public static void main(String args[]) {

if (args.length != 1) {

System.err.println("missing filename");

System.exit(1);

}

try {

FileInputStream fis = new FileInputStream(args[0]);

BufferedInputStream bis = new BufferedInputStream(fis);

int cnt = 0;

int b;

while ((b = bis.read()) != -1) {

if (b == '\n')

cnt++;

}

bis.close();

System.out.println(cnt);

} catch (IOException e) {

System.err.println(e);

}

}

}

BufferedInputStream.read 从输入缓冲区获取下一个字节,仅仅只访问了一次底层系统。

方法 3: 直接缓冲

第三种方法避免使用 BufferedInputStream 而直接缓冲,因此排除了 read 方法的调用:

import java.io.*;

public class intro3 {

public static void main(String args[]) {

if (args.length != 1) {

System.err.println("missing filename");

System.exit(1);

}

try {

FileInputStream fis = new FileInputStream(args[0]);

byte buf[] = new byte[2048];

int cnt = 0;

int n;

while ((n = fis.read(buf)) != -1) {

for (int i = 0; i < n; i++) {

if (buf[i] == '\n')

cnt++;

}

}

fis.close();

System.out.println(cnt);

} catch (IOException e) {

System.err.println(e);

}

}

}

对于一个1 MB 的输入文件,以秒为单位的执行时间是:

intro1   6.9 intro2   0.9 intro3   0.4

或者说在最慢的方法和最快的方法间是17比1的不同。

这个巨大的加速并不能证明你应该总是使用第三种方法,即自己做缓冲。这可能是一个错误的倾向特别是在处理文件结束事件时没有仔细的实现。在可读性上它也没有其它方法好。但是记住时间花费在哪儿了以及在必要的时候如何矫正是很有用。

方法2 或许是对于大多应用的 "正确" 方法.

加速I/O的基本规则的更多相关文章

  1. javaIO缓冲区

    java中IO类分类. 图来自网络 缓冲区:应用程序在内存中开辟的一个空间.用来放置需要被写入或写出的数据. 使用缓冲区的 优点:使得应用程序操作磁盘(或者说是与磁盘的通信)的次数降低,提高应用程序的 ...

  2. java io性能分析

    摘要: 本文大多技术围绕调整磁盘文件 I/O,但是有些内容也同样适合网络 I/O 和窗口输出. 第一部分技术讨论底层的I/O问题,然后讨论诸如压缩,格式化和串行化等高级I/O问题.然而这个讨论没有包含 ...

  3. 百度MIP移动页面加速——不只是CDN

    MIP是用CDN做加速的么?准确答案是:是,但不只是. MIP全称Mobile Instant Pages,移动网页加速器,是百度提出的页面加速解决方案.MIP从前端渲染和页面网络传输两方面进行优化, ...

  4. 【初码干货】使用阿里云对Web开发中的资源文件进行CDN加速的深入研究和实践

    提示:阅读本文需提前了解的相关知识 1.阿里云(https://www.aliyun.com) 2.阿里云CDN(https://www.aliyun.com/product/cdn) 3.阿里云OS ...

  5. 阿里云系列——6.给你的域名使用CDN加速(详细步骤+简单配置)

    网站部署之~阿里云系列汇总 http://www.cnblogs.com/dunitian/p/4958462.html 进入管理页面:https://home.console.aliyun.com/ ...

  6. Signalr系列之虚拟目录详解与应用中的CDN加速实战

    目录 对SignalR不了解的人可以直接移步下面的目录 SignalR系列目录 前言 前段时间一直有人问我 在用SignalR 2.0开发客服系统[系列1:实现群发通讯]这篇文章中的"/Si ...

  7. docker学习(2) mac中docker-machine使用vmware fusion以及配置国内镜像加速

    一.前言 先回顾下上一节创建docker-machine的过程,默认情况下docker toolbox中的docker-machine使用virtual box创建虚拟机,KI首次启动时创建虚拟机的过 ...

  8. [转]加速Android Studio/Gradle构建

    加速Android Studio/Gradle构建 android android studio gradle   已经使用Android Studio进行开发超过一年,随着项目的增大,依赖库的增多, ...

  9. 利用免费cdn加速webpack单页应用

    回顾现状 在之前的学习过程中,react单页应用经过webpack打包之后会输出大概如下的目录结构,它就是站点的所有前端组成了:   1 2 3 4 5 6 MacBook-Pro:output ba ...

随机推荐

  1. SonarQube install on Kubernetes

    Sonarqube搭建代码 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: postgres labels: app: ...

  2. HDU 1104 Remainder (BFS(广度优先搜索))

    Remainder Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  3. iOS mac添加证书 不能修改“System Roots”钥匙串错误

    iOS mac添加证书 不能修改“System Roots”钥匙串错误 如图: 解决方式: 打开钥匙串---登录---,直接把证书拖过来 然后,查看--我的证书,里面,找到证书,即可

  4. 镜像上传和Dockerfile

    一.镜像上传 1.在https://hub.docker.com 注册一个账号 2.创建一个仓库 3.取到containerID #docker ps 4.commit容器 #docker commi ...

  5. [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘终结篇:UniLua热更新全然解读

    ---------------------------------------------------------------------------------------------------- ...

  6. 遍历JavaScript某个对象所有的属性名称和值

    /* * 用来遍历指定对象所有的属性名称和值 * obj 需要遍历的对象 */ function allPrpos(obj) { // 用来保存所有的属性名称和值 var props = " ...

  7. Can rename table but can not truncate table

    一个表无法truncate可是能够rename,这个乍听起来认为好奇怪,以下模拟该过程. 3个session: session1运行truncate和rename操作. session2运行lock表 ...

  8. Mac 下安装Ruby环境(转)

    步骤1 - 安装 RVM RVM 是干什么的这里就不解释了,后面你将会慢慢搞明白. $ curl -L https://get.rvm.io | bash -s stable 期间可能会问你sudo管 ...

  9. SQL语句创建相同结构的表

    --Oracle的语句create table sa_salaryRecord as select * from sa_salary where 1=2; --MSSQL的语句select * int ...

  10. 纯div+css制作的弹出菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...