【发布时间】:2015-11-15 15:27:36
【问题描述】:
我被要求测量当前磁盘性能,因为我们计划在我们的应用服务器上用网络附加存储替换本地磁盘。由于我们写入数据的应用程序是用 Java 编写的,我想我会直接在 Linux 中测量性能,并使用简单的 Java 测试。然而,我得到了截然不同的结果,特别是在读取数据时,使用在我看来类似的测试。直接在Linux中我正在做:
dd if=/dev/zero of=/data/cache/test bs=1048576 count=8192
dd if=/data/cache/test of=/dev/null bs=1048576 count=8192
我的 Java 测试如下所示:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestDiskSpeed {
private byte[] oneMB = new byte[1024 * 1024];
public static void main(String[] args) throws IOException {
new TestDiskSpeed().execute(args);
}
private void execute(String[] args) throws IOException {
long size = Long.parseLong(args[1]);
testWriteSpeed(args[0], size);
testReadSpeed(args[0], size);
}
private void testWriteSpeed(String filePath, long size) throws IOException {
File file = new File(filePath);
BufferedOutputStream writer = null;
long start = System.currentTimeMillis();
try {
writer = new BufferedOutputStream(new FileOutputStream(file), 1024 * 1024);
for (int i = 0; i < size; i++) {
writer.write(oneMB);
}
writer.flush();
} finally {
if (writer != null) {
writer.close();
}
}
long elapsed = System.currentTimeMillis() - start;
String message = "Wrote " + size + "MB in " + elapsed + "ms at a speed of " + calculateSpeed(size, elapsed) + "MB/s";
System.out.println(message);
}
private void testReadSpeed(String filePath, long size) throws IOException {
File file = new File(filePath);
BufferedInputStream reader = null;
long start = System.currentTimeMillis();
try {
reader = new BufferedInputStream(new FileInputStream(file), 1024 * 1024);
for (int i = 0; i < size; i++) {
reader.read(oneMB);
}
} finally {
if (reader != null) {
reader.close();
}
}
long elapsed = System.currentTimeMillis() - start;
String message = "Read " + size + "MB in " + elapsed + "ms at a speed of " + calculateSpeed(size, elapsed) + "MB/s";
System.out.println(message);
}
private double calculateSpeed(long size, long elapsed) {
double seconds = ((double) elapsed) / 1000L;
double speed = ((double) size) / seconds;
return speed;
}
}
这是通过“java TestDiskSpeed /data/cache/test 8192”调用的
这两个都应该创建 8GB 的零文件,一次 1MB,测量速度,然后读回并再次测量。然而,我一直获得的速度是:
Linux:写入 - ~650MB/s
Linux:读取 - ~4.2GB/s
Java:写入 - ~500MB/s
Java:读取 - ~1.9GB/s
谁能解释这个巨大的差异?
【问题讨论】:
-
基本上你是在测试磁盘缓存的读取速度。那是你的目标吗?在这种情况下,Java 的开销可能很大。
-
这是 Martin Thompson 关于 Java I/O 性能的good post。
-
缓冲仅在您进行大量小读取时才有帮助。无论如何,我都会使用 NIO 进行这个读/写测试。
-
@peter 我对由 apangin 链接的 Martin 的代码进行了相当多的测试,我可以确认他的观察,即 NIO 代码需要很长时间才能预热,然后只能与普通阻塞 InputStream 相提并论。
-
@apangin 在 cmets 部分的深处有一个重要的观察结果:FileInputStream 的性能与 RandomAccessFile 一样好。
标签: java performance disk dd