[英]The fastest way to save large data to a file
我在Java,C#和C ++中做了一些数值计算。 其中一些保存了大量数据(到文本文件)。 最快的方法是什么?
C ++ 。
ofstream file;
file.open(plik);
for(int i=0;i<251;i++){
for(int j=0;j<81;j++)
file<<(i-100)*0.01<<" "<<(j-40)*0.01<<" "<<U[i][j]<<endl;
file<<endl;
}
我认为这是非常快的(我是对的吗:))
Java的
void SaveOutput(double[][] U, String fileName) throws IOException
{
PrintWriter tx = new PrintWriter(new FileWriter(fileName));
for(int i=0;i<251;i++)
{
for(int j=0;j<81;j++)
{
tx.println(String.format("%e %e %e ",(i - 100) * dz, (j - 40) * dz, U[i][j]));
}
tx.println();
}
tx.close();
}
C#示例类似。
这就是困扰我的事情。 我为每一行做了一个String对象(很多垃圾)。 在这个例子中它并不多,但有时我有10 000 000行。 这引出了我的问题:
谢谢
简介它。 运行代码,计时,看看需要多长时间。 如果花费的时间是可以接受的,请使用它。 如果没有,弄清楚哪个部分需要花费很长时间才能运行,并对其进行优化。
那个命令。 (有些人在这两个之前添加“make it run / build”......)
也就是说,我之前实际上已经在这类事情上运行指标。 缺点:你正在等待磁盘,而磁盘是非常缓慢的。 如果您使用C或C ++或Java编写它们并不重要,它们都在等待硬盘。
这是我在C中的各种I / O方法上做的上一篇文章 。不完全是您正在寻找的,但可能是提供信息的。
一个字:简介。
请注意,将std::endl
插入缓冲(文件)流会导致它刷新,这可能会降低性能(从语言POV开始,这意味着缓冲区被写入“out”,尽管这可能不一定意味着物理磁盘访问)。 要简单地打印换行符,请使用'\\n'
- 它永远不会更糟。
首先,最重要的是:使用缓冲的作家!
这可能包括在某些语言中启用通道缓冲或使用BufferedWriter(Java)或其他语言中的等效缓冲 。 如果不这样做可能会导致性能低得多,因为输出流可能会“过冲” - 上面的示例代码违反了这一点(FileWriter对缓冲一无所知)!
在许多情况下,人们可以认为CPU和主内存访问“便宜”和IO“昂贵” - 在这样的微不足道的情况下,改善对IO本身的访问(例如缓冲而不是[over] flushing)将导致最多有形的收益。 现代虚拟机和JIT做得非常好,短期对象分配/解除分配可能是这里“忧虑”最少的。
使用Java.nio类来创建通道。 频道是java的新手,比旧流快得多。 你也应该缓冲写入。 我不记得默认情况下通道是否缓冲。 我需要读一些告诉你的。
最后,你可以创建很多字符串。 你马上扔掉它们。 我怀疑它会让你写入磁盘变慢。 磁盘IO比CPU慢得多。
这就是我的想法:
fileChannel = new FileOutputStream("test.txt").getChannel();
for(int i=0;i<251;i++) {
for(int j=0;j<81;j++) {
fileChannel.write(ByteBuffer.wrap((String.format("%e %e %e ",(i - 100) * dz, (j - 40) * dz, U[i][j]) + "\n").toBytes());
}
fileChannel.close();
首先请注意,这个I / O绑定程序将根据小细节得到很大改进(例如,如果您使用C ++流或printf
)。
对于C / C ++部分,有人说使用printf
操作更快。 它可能更快,但不是那个数量级,所以我不会打扰。
至于Java版本,我认为它已经相当优化了。
不能告诉C#,我的医生不允许我:)
我希望在C或C ++中使用fprintf
会更快。
卢卡斯,
首先,我主要了解C#,所以这里的所有内容都与.NET有关。
根据您要处理的行数,我不会创建字符串或使用StringBuilder。 StringBuilder仅帮助从许多较小的段创建字符串。
我认为你最好的选择是使用文件系统对象的Stream版本。 这样,你根本就不存储字符串,所以你的内存使用量应该相当小。
此外,如果你真的缺少内存,你总是可以创建一个非托管字符串和P / Invoke。
埃里克
至于Java,您不必创建所有这些字符串。 摆脱String.format
并直接写入字节。
无情地使用nio和配置文件
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.