测试发现NIO性能没有FileWriter好!

铁衣 2016-02-23 12:02:55
我最近打算把应用里面写文件的性能提升一下。
一直以来都听说NIO能提升读写文件的性能,所以做了个测试。
但测试结果却发现NIO性能还不如传统的FileWriter。

方式一(传统方式):
FileWriter fw = new FileWriter("D:\\fileTest\\test.txt");
BufferedWriter bw = new BufferedWriter(fw);
long l = System.currentTimeMillis();
StringBuffer sub = null;
for (int i = 0; i < 200000; i++) {
sub = new StringBuffer();
for (int j = 0; j < 60; j++) {
sub.append("“很好,有些见地。”");
if (j < 39) {
sub.append(",");
}
}
bw.write(sub.toString());
bw.newLine();
}
bw.close();
System.out.println("执行时间:" + (System.currentTimeMillis() - l));
-----------------------------------------------------------
执行三次:
1.执行时间:1955
2.执行时间:1938
3.执行时间:1966

可以看出基本在2秒以内

方式二(NIO 缓冲区、通道方式):
FileOutputStream fos = new FileOutputStream(new File("D:\\fileTest\\test.txt"));
FileChannel fc = fos.getChannel();
ByteBuffer bb = ByteBuffer.allocate(2048);
long l = System.currentTimeMillis();
try {
StringBuffer sub = null;
for (int i = 0; i < 200000; i++) {
sub = new StringBuffer();
for (int j = 0; j < 60; j++) {
sub.append("“很好,有些见地。”");
if (j < 39) {
sub.append(",");
}
}
bb.put(sub.toString().getBytes());
bb.put("\n".toString().getBytes());
bb.flip();
fc.write(bb);
bb.clear();
}
fc.close();
fos.close();
System.out.println("执行时间:" + (System.currentTimeMillis() - l));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != fc) {
fc.close();
}
if (null != fos) {
fos.close();
}
}
-----------------------------------------------------------
执行三次:
执行时间:3255
执行时间:3022
执行时间:2996

从上面的测试结果看出,NIO的方式每次都需要3秒左右,性能更差。
是不是我的NIO代码写的有问题,请高手帮忙分析一下。
...全文
272 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
skgary 2016-02-29
  • 打赏
  • 举报
回复
引用 13 楼 carrd2008 的回复:
[quote=引用 12 楼 skgary 的回复:] [quote=引用 11 楼 carrd2008 的回复:] 你的意思我明白了。 那么请问,在我例子1的基础上,大幅度提升文件写入性能,应该怎么修改代码?
我把你的例子1的代码仔细跟踪了一下,其实大部分的性能都花在了CPU上面(90%以上) 其实真的用在写入磁盘的代码上的时间真的不多。[/quote] 嗯,应该是拼接StringBuffer的原因。 顺便问一下,你是通过什么方式检查CPU、磁盘I/O上各花费了多少时间的?[/quote] 你看一下BufferWriter的实现,如果你把buffer调整到200000*60*40以上,那基本上就没有磁盘IO了,对比一下速度。 当然还有很多别的工具,如jvisualvm监控一下
铁衣 2016-02-27
  • 打赏
  • 举报
回复
引用 12 楼 skgary 的回复:
[quote=引用 11 楼 carrd2008 的回复:] 你的意思我明白了。 那么请问,在我例子1的基础上,大幅度提升文件写入性能,应该怎么修改代码?
我把你的例子1的代码仔细跟踪了一下,其实大部分的性能都花在了CPU上面(90%以上) 其实真的用在写入磁盘的代码上的时间真的不多。[/quote] 嗯,应该是拼接StringBuffer的原因。 顺便问一下,你是通过什么方式检查CPU、磁盘I/O上各花费了多少时间的?
skgary 2016-02-26
  • 打赏
  • 举报
回复
引用 11 楼 carrd2008 的回复:
你的意思我明白了。 那么请问,在我例子1的基础上,大幅度提升文件写入性能,应该怎么修改代码?
我把你的例子1的代码仔细跟踪了一下,其实大部分的性能都花在了CPU上面(90%以上) 其实真的用在写入磁盘的代码上的时间真的不多。
铁衣 2016-02-25
  • 打赏
  • 举报
回复
引用 10 楼 skgary 的回复:
[quote=引用 8 楼 carrd2008 的回复:] [quote=引用 7 楼 skgary 的回复:] 楼主1的例子,如果 bw.write(sub.toString()); bw.newLine();之后加上bw.flush() 就会看到两个例子执行的时间基本上差不多了。
你的话我看不明白。 例子1本来就是性能比较好的,为什么要还加上bw.flush()? 加了这个后让例子1的性能下降,然后跟例子2差不多了。 这样做没什么意义吧。[/quote]
引用 8 楼 carrd2008 的回复:
[quote=引用 7 楼 skgary 的回复:] 楼主1的例子,如果 bw.write(sub.toString()); bw.newLine();之后加上bw.flush() 就会看到两个例子执行的时间基本上差不多了。
你的话我看不明白。 例子1本来就是性能比较好的,为什么要还加上bw.flush()? 加了这个后让例子1的性能下降,然后跟例子2差不多了。 这样做没什么意义吧。[/quote] 我要说的是:你比较的是NIO和FileWriter,但实际上,磁盘的读写性能其实和哪个都差不多,而在于你在应用这一层去直接磁盘读写的次数。 [/quote] 你的意思我明白了。 那么请问,在我例子1的基础上,大幅度提升文件写入性能,应该怎么修改代码?
skgary 2016-02-24
  • 打赏
  • 举报
回复
引用 8 楼 carrd2008 的回复:
[quote=引用 7 楼 skgary 的回复:] 楼主1的例子,如果 bw.write(sub.toString()); bw.newLine();之后加上bw.flush() 就会看到两个例子执行的时间基本上差不多了。
你的话我看不明白。 例子1本来就是性能比较好的,为什么要还加上bw.flush()? 加了这个后让例子1的性能下降,然后跟例子2差不多了。 这样做没什么意义吧。[/quote]
引用 8 楼 carrd2008 的回复:
[quote=引用 7 楼 skgary 的回复:] 楼主1的例子,如果 bw.write(sub.toString()); bw.newLine();之后加上bw.flush() 就会看到两个例子执行的时间基本上差不多了。
你的话我看不明白。 例子1本来就是性能比较好的,为什么要还加上bw.flush()? 加了这个后让例子1的性能下降,然后跟例子2差不多了。 这样做没什么意义吧。[/quote] 我要说的是:你比较的是NIO和FileWriter,但实际上,磁盘的读写性能其实和哪个都差不多,而在于你在应用这一层去直接磁盘读写的次数。
nomasp 2016-02-23
  • 打赏
  • 举报
回复
给你贴一篇之前看的博客…… http://www.longda.us/?p=483
铁衣 2016-02-23
  • 打赏
  • 举报
回复
引用 7 楼 skgary 的回复:
楼主1的例子,如果 bw.write(sub.toString()); bw.newLine();之后加上bw.flush() 就会看到两个例子执行的时间基本上差不多了。
你的话我看不明白。 例子1本来就是性能比较好的,为什么要还加上bw.flush()? 加了这个后让例子1的性能下降,然后跟例子2差不多了。 这样做没什么意义吧。
skgary 2016-02-23
  • 打赏
  • 举报
回复
楼主1的例子,如果 bw.write(sub.toString()); bw.newLine();之后加上bw.flush() 就会看到两个例子执行的时间基本上差不多了。
skgary 2016-02-23
  • 打赏
  • 举报
回复
楼主比的是buffered方式和nio方式比较吧,把buffer去掉就更明显看的出结果了。在磁盘IO读写方面,最重要的仍然是物理读写的次数。这些一般在自己的代码里可以优化。 NIO其实是在网络IO方面性能提升明显,但是,不是单个tcp连接,而是多个(大于200)连接时,线程数明显节约,减少了CPU的调度来提升的。
铁衣 2016-02-23
  • 打赏
  • 举报
回复
引用 3 楼 rui888 的回复:

	public static void main(String[] args) throws IOException {
		long l = System.currentTimeMillis();
		BufferedReader br = null;
		String sCurrentLine = null;
		try {
			br = new BufferedReader(new FileReader("test.txt"));
			while ((sCurrentLine = br.readLine()) != null) {
				// System.out.println(sCurrentLine);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null)
					br.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		System.out.println("IO执行时间:" + (System.currentTimeMillis() - l));

		l = System.currentTimeMillis();
		RandomAccessFile aFile = new RandomAccessFile("test.txt", "r");
		FileChannel inChannel = aFile.getChannel();
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while (inChannel.read(buffer) > 0) {
			buffer.flip();
			for (int i = 0; i < buffer.limit(); i++) {
				// System.out.print((char) buffer.get());
			}
			buffer.clear(); // do something with the data and clear/compact it.
		}
		inChannel.close();
		aFile.close();
		System.out.println("NIO执行时间:" + (System.currentTimeMillis() - l));
	}
居然用RandomAccessFile的方式最慢了。 下面是我的代码,一样是执行三次:

FileUtil.createFile("D:\\fileTest\\test.txt");
        RandomAccessFile aFile = new RandomAccessFile("D:\\fileTest\\test.txt", "rw");
        FileChannel channel = aFile.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(2048);
        StringBuffer sub = null;
        long l = System.currentTimeMillis();
        for (int i = 0; i < 200000; i++) {
            sub = new StringBuffer();
            for (int j = 0; j < 60; j++) {
                sub.append("“很好,有些见地。”");
                if (j < 39) {
                    sub.append(",");
                }
            }
            buffer.put(sub.toString().getBytes());
            buffer.put("\r\n".getBytes());
            buffer.flip();
            channel.write(buffer);
            buffer.clear();
        }
        channel.close();
        aFile.close();
        System.out.println("执行时间:" + (System.currentTimeMillis() - l));
--------------------------------------------------------------- 1.执行时间:3667 2.执行时间:3320 3.执行时间:3353 三观被颠覆了,能不能解释一下。
铁衣 2016-02-23
  • 打赏
  • 举报
回复
引用 1 楼 bobolnear 的回复:
请参考 这个 http://bbs.csdn.net/topics/390658408?page=1 nio主要还是在网络io这一块对性能的提升比较明显,是来自于线程模型的进步,这一点是毋庸置疑的 另外文件io的话,我记得nio里好像有一个方法可以把小文件map到内存来操作,这个api旧io里好像是没有的,这个api对性能的帮助也比较大
那是内存映射文件,这个还没试过。 我去试试看。
tony4geek 2016-02-23
  • 打赏
  • 举报
回复

	public static void main(String[] args) throws IOException {
		long l = System.currentTimeMillis();
		BufferedReader br = null;
		String sCurrentLine = null;
		try {
			br = new BufferedReader(new FileReader("test.txt"));
			while ((sCurrentLine = br.readLine()) != null) {
				// System.out.println(sCurrentLine);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null)
					br.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		System.out.println("IO执行时间:" + (System.currentTimeMillis() - l));

		l = System.currentTimeMillis();
		RandomAccessFile aFile = new RandomAccessFile("test.txt", "r");
		FileChannel inChannel = aFile.getChannel();
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while (inChannel.read(buffer) > 0) {
			buffer.flip();
			for (int i = 0; i < buffer.limit(); i++) {
				// System.out.print((char) buffer.get());
			}
			buffer.clear(); // do something with the data and clear/compact it.
		}
		inChannel.close();
		aFile.close();
		System.out.println("NIO执行时间:" + (System.currentTimeMillis() - l));
	}
tony4geek 2016-02-23
  • 打赏
  • 举报
回复
bobolnear 2016-02-23
  • 打赏
  • 举报
回复
请参考 这个 http://bbs.csdn.net/topics/390658408?page=1 nio主要还是在网络io这一块对性能的提升比较明显,是来自于线程模型的进步,这一点是毋庸置疑的 另外文件io的话,我记得nio里好像有一个方法可以把小文件map到内存来操作,这个api旧io里好像是没有的,这个api对性能的帮助也比较大

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧