背景
最近在看socket编程,这里面需要用到stream进行数据的读取和写入。于是代码中用到了BufferedInputStream提高读的效率。所以就一直在想为什么加上buffer就能提高效率了,加上之前面试的时候曾有面试官问到过这个问题,当时没有回答上来,并且就上网搜索了一下,发现有个文章是为什么缓存能提高io效率,这个文章中说是因为缓存可以让DMA来处理io流,后面我一直都是这么认为的,今天在网上搜索发现即使你用的是inputstream来读也会用到DMA,那篇文章中的缓存可能指的是内核态的缓存。所以之前以为的应该都是错误的吧。
猜想
在进行io流的读时,最消耗时间的应该是数据从内核态拷贝到用户态这个过程,这个过程会进行上下文的切换,详细的内容可以搜索一下。
接下来看一下BufferedInputStream的代码。
1、首先是初始化,如果不指定缓冲区的大小,会默认8192长度的数组
2、查看BufferedInputStream的read()方法。
read()方法中有个fill()方法,这里的read()方法其实是加锁的,猜想应该是防止多线程调用的时候造成缓存数组的数据混乱,查看full方法的调用的是原生inputstream的public int read(byte b[], int off, int len) throws IOException 方法,注意这里第一个参数是传入了一个byte数组。
分析
既然BufferedInputStream的read()方法最终还是会调用FileInputStream的read方法,那是不是所如果直接使用FileInputStream的public int read(byte b[]) 方法也能提高效率。
用三种方法读取7.8M的文件,测试结果如下:
结果基本可以看出使用原生FileInputStream的read(byte[] b)方法效率也是可以高很多的
测试代码
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author
* @Description
* @create 2022-02-17 14:56
*/
public class TestInputStream {
private final static String FILENAME = "input-test.txt";
public static void main(String[] args) {
testOutputStream();
testInputStream(false);
testInputStream(true);