我正在尝试从 java 程序创建 300M 文件,我从旧文件 API 切换到新的 java 7 nio 包,但新包比旧包更慢。
与使用旧文件 API 时相比,我发现 CPU 利用率较低,但我正在运行这个简单的代码,我获得了 0.5 兆字节/秒的文件传输速率,并且来自 java 的写入正在从一个磁盘读取并写入另一个(写入是访问磁盘的唯一进程)。
Files.write(FileSystems.getDefault().getPath(filePath), fiveToTenKBytes, StandardOpenOption.CREATE);
这里有没有希望得到合理的吞吐量?
更新:
我正在从大文件中解压 3 亿个 5-10k 字节的图像文件。我有 3 个磁盘,1 个本地磁盘和 2 个 SAN 连接(大文件的典型吞吐率约为 20MB/秒)。
我也试过这段代码,它可以将速度提高到略低于 2MB/秒的吞吐量(解压这些文件需要 9 天左右的时间)。
ByteBuffer byteBuffer = ByteBuffer.wrap(imageBinary, 0, (BytesWritable)value).getLength());
FileOutputStream fos = new FileOutputStream( imageFile );
fos.getChannel().write(byteBuffer);
fos.close();
我从本地磁盘读取并写入 SAN 附加磁盘。我正在读取 Hadoop SequenceFile 格式,hadoop 通常能够使用基本相同的代码以 20MB/秒的速度读取这些文件。
唯一看起来不合适的地方,除了 super 慢之外,我看到读取 IO 比写入 IO 多大约 2:1,尽管序列文件是 gzip 压缩的(尽管图像实际上是 1:1 的比例) ), 所以压缩文件应该是大约。 1:1 与输出。
第二次更新
查看 iostat
我看到一些奇数,我们在这里查看 xvdf,我有一个 java 进程从 xvdb
读取并写入 xvdf
并且没有其他进程在 xvdf
iostat -d 30
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvdap1 1.37 5.60 4.13 168 124
xvdb 14.80 620.00 0.00 18600 0
xvdap3 0.00 0.00 0.00 0 0
xvdf 668.50 2638.40 282.27 79152 8468
xvdg 1052.70 3751.87 2315.47 112556 69464
xvdf
上的读取是写入的 10 倍,这令人难以置信。
fstab
/dev/xvdf /mnt/ebs1 auto defaults,noatime,nodiratime 0 0
/dev/xvdg /mnt/ebs2 auto defaults,noatime,nodiratime 0 0
最佳答案
如果我对您的代码的理解正确,那么您就是将 300M 的文件分成小块(“fiveToTenKBytes
”)。
考虑使用a Stream approach .
如果您要写入磁盘,请考虑使用 BufferedOutputStream 包装 OutputStream。
例如像这样的东西:
try (BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(Paths.getPath(filePathString), StandardOpenOption.CREATE))){
...
}
关于Java 7 的 nio.file 包在创建新文件时非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15433823/