我在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;
}
我认为这是非常快的(我是对的吗?:))
爪哇
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行。这引出了我的问题:
谢谢
答案 0 :(得分:5)
描述它。运行代码,计时,看看需要多长时间。如果花费的时间是可以接受的,请使用它。如果没有,弄清楚哪个部分需要花费很长时间才能运行,并对其进行优化。
那个命令。 (有些人在这两个人之前添加“make it run / build”...)
那就是说,我之前实际上已经在这类事情上运行指标。缺点:你正在等待磁盘,而磁盘是非常缓慢的。如果您使用C或C ++或Java编写它们并不重要,它们都在等待硬盘。
这是我在C中的各种I / O方法所做的previous post。不完全是您正在寻找的,但可能提供信息。
答案 1 :(得分:4)
一个字:简介。
请注意,将std::endl
插入缓冲(文件)流会导致其刷新,这可能会降低性能(从语言POV开始,这意味着缓冲区被“写出”,尽管这可能不一定表示物理磁盘访问)。要简单地打印换行符,请使用'\n'
- 它永远不会更糟。
答案 2 :(得分:2)
首先,最重要的是:使用缓冲的作家!
这可能包括在某些语言中启用频道缓冲,或在其他语言中使用BufferedWriter (in Java)或等效语言。如果不这样做可能会导致性能低得多,因为输出流可能会“过冲” - 上面的示例代码违反了这一点(FileWriter对缓冲一无所知)!
在许多情况下,人们可以认为CPU和主内存访问“便宜”而IO“昂贵” - 在这样的微不足道的情况下,将改善对IO本身的访问(例如缓冲而不是[over] flushing)将导致在最切实的收益。现代虚拟机和JIT做得非常好,短期对象分配/解除分配可能是这里“忧虑”最少的。
答案 3 :(得分:1)
使用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();
答案 4 :(得分:1)
首先请注意,根据细节的不同,这个I / O绑定程序将得到很大的改进(例如,如果您使用C ++流或printf
)。
对于C / C ++部分,有人说使用ol'printf
操作更快。 可能更快,但不是那个数量级,所以我不会打扰。
对于Java版本,我认为它已经相当优化。
无法告诉C#,我的医生不允许我:)
答案 5 :(得分:0)
我希望在C或C ++中使用fprintf
会更快。
答案 6 :(得分:0)
的Lukas,
首先,我主要了解C#,所以这里的所有内容都与.NET有关。
根据您要处理的行数,我不会创建字符串或使用StringBuilder。 StringBuilder仅帮助从许多较小的段创建字符串。
我认为您最好的选择是使用文件系统对象的Stream版本。这样,你根本就不存储字符串,所以你的内存使用量应该相当小。
此外,如果你的内存非常缺乏,你可以随时创建一个非托管字符串和P / Invoke。
埃里克
答案 7 :(得分:0)
对于Java,您不必创建所有这些字符串。摆脱String.format
并直接写入字节。
无情地使用nio和个人资料