相关疑难解决方法(0)

真的在Java中强制文件同步/刷新

如何通过Java 真正使用块设备刷新/同步写入文件的数据.

我用NIO试过这段代码:

FileOutputStream s = new FileOutputStream(filename)
Channel c = s.getChannel()
while(xyz)
    c.write(buffer)
c.force(true)
s.getFD().sync()
c.close()
Run Code Online (Sandbox Code Playgroud)

我认为c.force(true)与s.getFD()同步.sync()应该足够了,因为强制状态的文档

强制将此通道文件的任何更新写入包含它的存储设备.如果此通道的文件驻留在本地存储设备上,则当此方法返回时,保证自创建此通道以来对文件所做的所有更改,或者自上次调用此方法以来,该文件都将写入该设备.这对于确保在系统崩溃时不会丢失关键信息非常有用.

同步状态的文档:

强制所有系统缓冲区与底层设备同步.在将此FileDescriptor的所有已修改数据和属性写入相关设备之后,此方法返回.特别是,如果此FileDescriptor引用物理存储介质(例如文件系统中的文件),则在将与此FileDesecriptor关联的缓冲区的所有内存中修改副本写入物理介质之前,不会返回sync.sync意味着需要物理存储(例如文件)处于已知状态的代码.

这两个电话应该足够了.是吗?我猜他们不是.

背景:我使用C/Java进行小的性能比较(2 GB,顺序写入),Java版本的速度是C版本的两倍,可能比硬件速度快(单个HD上的速度为120 MB/s).我还尝试使用Runtime.getRuntime().exec("sync")执行命令行工具同步,但这并没有改变行为.

导致70 MB/s的C代码(使用低级API(打开,写入,关闭)不会发生太大变化):

FILE* fp = fopen(filename, "w");
while(xyz) {
    fwrite(buffer, 1, BLOCK_SIZE, fp);
}
fflush(fp);
fclose(fp);
sync();
Run Code Online (Sandbox Code Playgroud)

没有最后的同步调用; 我得到了不切实际的价值(超过1 GB又称主内存性能).

为什么C和Java之间有这么大的差异?有两种可能性:我没有在Java中正确地同步数据,或者C代码由于某种原因是次优的.

更新:我已经使用"strace -cfT cmd"完成了strace运行.结果如下:

C(低级API):MB/s 67.389782

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 87.21    0.200012      200012         1           fdatasync
 11.05    0.025345           1     32772           write
  1.74    0.004000 …

java storage

36
推荐指数
3
解决办法
2万
查看次数

标签 统计

java ×1

storage ×1