Dav*_*rks 6 java file-io java-7 nio2
我正在尝试从java程序创建300M文件,我从旧的文件API切换到新的java 7 nio包,但是新的包比旧的更慢.
我看到的CPU利用率低于使用旧文件API时的CPU利用率,但我正在运行这个简单的代码,我得到0.5Mbytes/sec的文件传输速率,而java的写入正在读取一个磁盘并写入另一个(写入是访问磁盘的唯一进程).
Files.write(FileSystems.getDefault().getPath(filePath), fiveToTenKBytes, StandardOpenOption.CREATE);
Run Code Online (Sandbox Code Playgroud)
有没有希望在这里获得合理的吞吐量?
更新:
我正在从大文件中解包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();
Run Code Online (Sandbox Code Playgroud)
我从本地磁盘读取并写入SAN连接磁盘.我正在阅读Hadoop SequenceFile格式,hadoop通常能够使用基本相同的代码以20MB /秒的速度读取这些文件.
除了超级缓慢之外,唯一看起来不合适的是,我看到更多的读取IO比写入IO大约2:1,尽管序列文件是gziped(图像实际上比例为1:1),所以压缩文件应该是约.输出1:1.
第二次更新
看着iostat我看到一些奇怪的数字,我们在这里看xvdf,我有一个java进程读取xvdb和写入xvdf并且没有活动的ohter进程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
Run Code Online (Sandbox Code Playgroud)
读取xvdf是写入的10倍,这是令人难以置信的.
fstab
/dev/xvdf /mnt/ebs1 auto defaults,noatime,nodiratime 0 0
/dev/xvdg /mnt/ebs2 auto defaults,noatime,nodiratime 0 0
Run Code Online (Sandbox Code Playgroud)
我认为你的缓慢是来自创建新文件,而不是实际传输。我相信在Linux中创建文件是一个同步操作:系统调用在文件创建和目录更新之前不会返回。这建议您可以做几件事:
byte[],然后创建一个Runnable从此数组写入输出文件的文件。使用具有大量线程(可能是 100 个或更多)的线程池,因为它们将花费大部分时间等待完成creat。根据您拥有的内存量设置此池的入站队列的容量:如果您的文件大小为 10k,那么队列容量 1,000 似乎是合理的(没有充分的理由允许读者比编写者走得太远) ,因此您甚至可以使用两倍线程数的容量)。BufferedInputStream使用 basic s 和,而不是 NIO BufferedOutputStreams。这里的问题是系统调用,而不是内存速度(NIO 类旨在防止堆内存和堆外内存之间的复制)。我假设您已经知道不要尝试将所有文件存储到单个目录中。甚至在一个目录中存储数百个以上的文件。
作为另一种选择,您是否考虑过使用 S3 进行存储?我猜测它的存储桶键比实际目录更有效,并且有一个文件系统可以让您像访问文件一样访问存储桶(我自己还没有尝试过)。