Java IO学习笔记一:为什么带Buffer的比不带Buffer的快
作者:Grey
原文地址:Java IO学习笔记一:为什么带Buffer的比不带Buffer的快
Java中为什么BufferedReader,BufferedWriter要比FileReader 和 FileWriter高效?
问题来自于:https://www.zhihu.com/question/29351698
其中R大的一个回答:

现在我们可以通过实验来说明这个问题:
环境:CentOS 7, jdk1.8
首先,写一个不带buffer的代码
static byte[] data = "123456789\n".getBytes();
static String path = "/data/io/out.txt";
public static void testBasicFileIO() throws Exception {
File file = new File(path);
FileOutputStream out = new FileOutputStream(file);
while (true) {
out.write(data);
}
}
同时,我们写一个带buffer的代码
public static void testBufferedFileIO() throws Exception {
File file = new File(path);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
while (true) {
out.write(data);
}
}
通过main函数的args参数来控制执行哪个方法,完整代码为:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
public class OSFileIO {
static byte[] data = "123456789\n".getBytes();
static String path = "/data/io/out.txt";
public static void main(String[] args) throws Exception {
switch (args[0]) {
case "0":
testBasicFileIO();
break;
case "1":
testBufferedFileIO();
break;
default:
break;
}
}
public static void testBasicFileIO() throws Exception {
File file = new File(path);
FileOutputStream out = new FileOutputStream(file);
while (true) {
out.write(data);
}
}
public static void testBufferedFileIO() throws Exception {
File file = new File(path);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
while (true) {
out.write(data);
}
}
}
在Linux(先安装好jdk1.8)中,准备好目录:
mkdir -p /data/io
安装必要工具
yum install -y strace lsof pmap tcpdump
将OSFileIO.java这个类上传到/data/io目录下,在/data/io目录下,新建一个mysh.sh的脚本,脚本内容如下:
rm -rf *out*
/usr/local/jdk/bin/javac OSFileIO.java
strace -ff -o out /usr/local/jdk/bin/java OSFileIO $1
赋予mysh.sh执行权限
chmod +x /data/io/mysh.sh
先监控带buffer的writer和不带buffer的writer的写效率,
不带buffer的writer效率,在控制台执行:
./mysh.sh 0
打开另外一个控制台,进入/data/io目录,监控生成out文件大小的速度,不断执行
ll -h
可以看到out.txt的增长速度
-rw-r--r--. 1 root root 2.1M Jun 10 19:50 out.txt
...
-rw-r--r--. 1 root root 5.3M Jun 10 19:51 out.txt
重新执行,使用带buffer的writer
./mysh.sh 1
在另外一个控制台,进入/data/io目录,继续监控out.txt的增长
cd /data/io
ll -h
可以看到out.txt的增长速度明显更快
-rw-r--r--. 1 root root 290M Jun 10 19:54 out.txt
....
-rw-r--r--. 1 root root 768M Jun 10 19:54 out.txt
....
-rw-r--r--. 1 root root 1.4G Jun 10 19:55 out.txt
这个是表现,我们再观察一下使用buffer和未使用buffer的writer在执行的时候,系统调用的次数。
重新执行
./mysh.sh 0
执行大约10秒后,停止执行
由于mysh.sh中使用了strace, 可以用于跟踪和分析进程执行时中系统调用和耗时以及占用cpu的比例
查看生成的out文件列表:
[root@io io]# ll
total 60708
-rwxr-xr-x. 1 root root 106 Jun 10 19:25 mysh.sh
-rw-r--r--. 1 root root 3981 Jun 10 20:08 OSFileIO.class
-rw-r--r--. 1 root root 4587 Jun 10 19:29 OSFileIO.java
-rw-r--r--. 1 root root 9379 Jun 10 20:10 out.6916
-rw-r--r--. 1 root root 50363725 Jun 10 20:10 out.6917
-rw-r--r--. 1 root root 1027 Jun 10 20:10 out.6918
-rw-r--r--. 1 root root 885 Jun 10 20:10 out.6919
-rw-r--r--. 1 root root 850 Jun 10 20:10 out.6920
-rw-r--r--. 1 root root 948 Jun 10 20:10 out.6921
-rw-r--r--. 1 root root 885 Jun 10 20:10 out.6922
-rw-r--r--. 1 root root 885 Jun 10 20:10 out.6923
-rw-r--r--. 1 root root 850 Jun 10 20:10 out.6924
-rw-r--r--. 1 root root 1134 Jun 10 20:10 out.6925
-rw-r--r--. 1 root root 26835 Jun 10 20:10 out.6926
-rw-r--r--. 1 root root 1343 Jun 10 20:10 out.6927
-rw-r--r--. 1 root root 1210 Jun 10 20:10 out.6928
-rw-r--r--. 1 root root 2324 Jun 10 20:10 out.6929
-rw-r--r--. 1 root root 9954 Jun 10 20:10 out.6930
-rw-r--r--. 1 root root 9792 Jun 10 20:10 out.6931
-rw-r--r--. 1 root root 9477 Jun 10 20:10 out.6932
-rw-r--r--. 1 root root 8295 Jun 10 20:10 out.6933
-rw-r--r--. 1 root root 1190 Jun 10 20:10 out.6934
-rw-r--r--. 1 root root 485668 Jun 10 20:10 out.6935
-rw-r--r--. 1 root root 2008 Jun 10 20:10 out.7023
-rw-r--r--. 1 root root 11152490 Jun 10 20:10 out.txt
可以看到
-rw-r--r--. 1 root root 50363725 Jun 10 20:10 out.6917
是主线程生成的系统调用,查看这个文件,可以看到,系统调用write的次数很多
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
write(4, "123456789\n", 10) = 10
切换成带buffer的执行,大约执行10秒
./mysh.sh 1
同样可以通过ll查看
[root@io io]# ll
total 388808
-rwxr-xr-x. 1 root root 106 Jun 10 19:25 mysh.sh
-rw-r--r--. 1 root root 3981 Jun 10 20:17 OSFileIO.class
-rw-r--r--. 1 root root 4587 Jun 10 19:29 OSFileIO.java
-rw-r--r--. 1 root root 9526 Jun 10 20:18 out.7053
-rw-r--r--. 1 root root 3262847 Jun 10 20:18 out.7054
-rw-r--r--. 1 root root 1076 Jun 10 20:18 out.7055
-rw-r--r--. 1 root root 885 Jun 10 20:18 out.7056
-rw-r--r--. 1 root root 885 Jun 10 20:18 out.7057
-rw-r--r--. 1 root root 948 Jun 10 20:18 out.7058
-rw-r--r--. 1 root root 983 Jun 10 20:18 out.7059
-rw-r--r--. 1 root root 948 Jun 10 20:18 out.7060
-rw-r--r--. 1 root root 885 Jun 10 20:18 out.7061
-rw-r--r--. 1 root root 1099 Jun 10 20:18 out.7062
-rw-r--r--. 1 root root 3812 Jun 10 20:18 out.7063
-rw-r--r--. 1 root root 1259 Jun 10 20:18 out.7064
-rw-r--r--. 1 root root 1245 Jun 10 20:18 out.7065
-rw-r--r--. 1 root root 2337 Jun 10 20:18 out.7066
-rw-r--r--. 1 root root 6415 Jun 10 20:18 out.7067
-rw-r--r--. 1 root root 5486 Jun 10 20:18 out.7068
-rw-r--r--. 1 root root 6347 Jun 10 20:18 out.7069
-rw-r--r--. 1 root root 4972 Jun 10 20:18 out.7070
-rw-r--r--. 1 root root 1008 Jun 10 20:18 out.7071
-rw-r--r--. 1 root root 25438 Jun 10 20:18 out.7072
-rw-r--r--. 1 root root 2071 Jun 10 20:18 out.7073
-rw-r--r--. 1 root root 394725240 Jun 10 20:18 out.txt
其中
-rw-r--r--. 1 root root 3262847 Jun 10 20:18 out.7054
为主线程的系统调用,打开这个文件可以看到
write(4, "123456789\n123456789\n123456789\n12"..., 8190) = 8190
write(4, "123456789\n123456789\n123456789\n12"..., 8190) = 8190
write(4, "123456789\n123456789\n123456789\n12"..., 8190) = 8190
write(4, "123456789\n123456789\n123456789\n12"..., 8190) = 8190
write(4, "123456789\n123456789\n123456789\n12"..., 8190) = 8190
write(4, "123456789\n123456789\n123456789\n12"..., 8190) = 8190
不是每次写都调用系统的write,而是凑齐8190后再调用一次系统的write,所以速度更快。
源码:Github
Java IO学习笔记一:为什么带Buffer的比不带Buffer的快的更多相关文章
- Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer
作者:Grey 原文地址:Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer ByteBuffer.allocate()与ByteBuffer.allocateD ...
- Java IO学习笔记六:NIO到多路复用
作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...
- Java IO学习笔记五:BIO到NIO
作者:Grey 原文地址: Java IO学习笔记五:BIO到NIO 准备环境 准备一个CentOS7的Linux实例: 实例的IP: 192.168.205.138 我们这次实验的目的就是直观感受一 ...
- Java IO学习笔记七:多路复用从单线程到多线程
作者:Grey 原文地址:Java IO学习笔记七:多路复用从单线程到多线程 在前面提到的多路复用的服务端代码中, 我们在处理读数据的同时,也处理了写事件: public void readHandl ...
- Java IO学习笔记八:Netty入门
作者:Grey 原文地址:Java IO学习笔记八:Netty入门 多路复用多线程方式还是有点麻烦,Netty帮我们做了封装,大大简化了编码的复杂度,接下来熟悉一下netty的基本使用. Netty+ ...
- Java IO学习笔记:概念与原理
Java IO学习笔记:概念与原理 一.概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络)读入到内存 中,形成了 ...
- Java IO学习笔记总结
Java IO学习笔记总结 前言 前面的八篇文章详细的讲述了Java IO的操作方法,文章列表如下 基本的文件操作 字符流和字节流的操作 InputStreamReader和OutputStreamW ...
- Java IO学习笔记三
Java IO学习笔记三 在整个IO包中,实际上就是分为字节流和字符流,但是除了这两个流之外,还存在了一组字节流-字符流的转换类. OutputStreamWriter:是Writer的子类,将输出的 ...
- Java IO学习笔记二
Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...
随机推荐
- 工具tip
1 postman: chrome的插件,模拟http的get.post等各种请求 2 010: 二进制文件查看,支持很多文件格式和强大的脚本:010 Editor体验 3 BeyondCompare ...
- 用最容易的方式学会单链表(Python实现)
单链表与数组 在本博客中,我们介绍单链表这种数据结构,链表结构为基于数组的序列提供了另一种选择(例如Python列表). 基于数组的序列也会有如下缺点: 一个动态数组的长度可能超过实际存储数组元素所需 ...
- (Py练习)输出乘法口诀表
#输出9*9乘法口诀表 for i in range(1,10): for j in range(1,i+1): print("%d*%d=%2d"%(i,j,i*j),end = ...
- 【SpringMVC】数据校验时,抛出javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: java.util.Date.
老魏原创,转载请留言. 原因:给Javabean中的字段注解多余或者错误导致. @NotEmpty @Past @DateTimeFormat(pattern="yyyy-MM-dd&quo ...
- Django(1)初识Django
前言 Django是一个开放源代码的Web应用框架,由Python写成,最初用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站,即CMS(内容管理系统)软件,于2005年7月在BSD许可证下发布,这 ...
- Morgan Stanley Books List:经典金融书籍推荐
一.经济学 1. 中华帝国的专制制度,佛朗索瓦.魁奈 2. 资本论(共3卷),马恩全集 3. 国家竞争优势,麦克尔.波特 4. Essentials of corporate analysis, by ...
- 3D教育类小图标_三维立体学习类icon图标素材
3D教育类小图标_三维立体学习类icon图标素材
- python3读取文件指定行的三种方案
技术背景 考虑到深度学习领域中的数据规模一般都比较大,尤其是训练集,这个限制条件对应到实际编程中就意味着,我们很有可能无法将整个数据文件的内容全部都加载到内存中.那么就需要一些特殊的处理方式,比如:创 ...
- [笔记] 《c++ primer》书店程序 Chapter7
Sales_data.h 1 #ifndef SALES_DATA_H 2 #define SALES_DATA_H 3 4 #include "Version_test.h" 5 ...
- mysql默认值
1.创建表时添加默认值 语法: <字段名><类型><默认值> 实例: MySQL [wordpress]> create table ly_content( ...