将大型数据保存到文件的最快方法
我在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对象(很多垃圾)。在这个例子中,它并不多,但有时候我有1000万行。这引出了我的问题:
- c + +示例可以更快吗?
- 我是否应该使用StringBuilder for Java或者它也可能由于行数差而不好
- 还有其他方法或库吗?
- C#呢?
谢谢
简介它。运行代码,计时,查看需要多长时间。如果花费的时间可以接受,请使用它。如果不是的话,找出哪些部分需要花费很长时间才能运行,并对其进行优化。
- 作出正确选择。
- 快点。
该订单。 (有些人在这两个之前添加“让它运行/构建”)
也就是说,我之前已经在这种事情上运行过度量标准。缺点是:您正在等待磁盘,而磁盘速度很慢。不管你用C或C++还是Java编写,他们都在等待硬盘。
这里有一个previous post我在C.做了各种I/O方法,您正在寻找不完全是,但可能是提供信息。
分析对于I/O绑定程序很难。 – 2010-11-04 23:13:32
它总是可以接受的因为我可以在夜间运行它。我正在寻找一些提示或模式,比如当我开始用Java编程时,我使用了类似tx.println(val1 +“”+ val2 +“”+等)的东西,这有点愚蠢,并且使得我的计算变得更慢 – 2010-11-04 23:22:58
@ lukas真的吗?在现代javac版本中,你有一个+ b + c的基准测试比一个StringBuilder慢吗(对于一些相当长的a,b和c)? – 2010-11-04 23:31:57
改为使用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();
哎呀忘了添加到BY():) – 2010-11-04 23:29:05
AFAIK真的没有理由使用NIO,除非需要选择器(非阻塞IO), mmap或其他“额外”功能。 “旧”Java IO API对于阻塞读/写操作来说同样快,并且多线程IO不是(总是)比选择器/ nb IO慢。 – 2010-11-04 23:50:13
那总是不正确的。根据操作系统的不同,使用nio可能会更快。 http://*.com/questions/1605332/java-nio-filechannel-versus-fileoutputstream-performance-usefulness – 2010-11-05 01:18:24
一个字:档案。
请注意,将std::endl
插入到缓冲(文件)流会导致其刷新,这可能会降低性能(从语言POV意味着缓冲区被写入“out”,尽管这可能不一定意味着物理磁盘访问)。对于简单地打印换行,请使用'\n'
- 它永远不会更糟。
+1对'endl'造成冲洗。 – Thanatos 2010-11-04 23:28:32
请注意,首先,根据小细节(例如,如果使用C++流或printf
),此I/O绑定程序将不会得到太多改进。
对于C/C++部分,有人说使用ol'printf
操作会更快。它可能会更快,但不是那么重要,所以我不打扰。
至于Java版本,我认为它已经相当优化了。
不能告诉了C#,我的医生不允许我:)
卢卡斯,
首先,我知道主要是C#,所以这里的一切涉及到.NET。
随着你处理的行数,我不会创建字符串或使用StringBuilder。一个StringBuilder只能帮助从一些较小的段创建字符串。
我认为你最好的选择是使用Stream版本的文件系统对象。这样,你根本不存储字符串,所以你的内存使用量应该很小。另外,如果你真的对内存不够用,你总是可以创建一个非托管字符串和P/Invoke。
Erick
至于Java,您不必创建所有这些字符串。摆脱String.format
并直接写入字节。
使用NiO和配置文件无情
首先,也是最重要的:使用一个缓冲的作家!
这可能包括启用某些语言在频道上的缓冲或使用BufferedWriter (in Java)或其他等效语言。如果不这样做,可能会导致性能远低于,因为输出流可能会“过度刷新” - 上面的示例代码违反了此规定(FileWriter对缓冲没有任何知识)!
在许多情况下,人们可以考虑CPU和主存储器访问“廉价”和IO“昂贵” - 在这种微不足道的情况下,改进对IO本身的访问(例如缓冲和不冲洗)导致最显着的收益。现代的虚拟机和JIT做他们做得很好的事情,短暂的对象分配/解除分配可能是这里“最担心的问题”。
只是一个快速提示,使用''n''而不是'endl',因为'endl'强制每一行刷新数据流 – Inverse 2010-11-05 00:23:28
它是否必须是文本文件?以二进制形式保存可能会显着加快速度。你在运行什么操作系统?可能有操作系统特定的功能(例如Windows中重叠的I/O)可以加快速度。 – 2010-11-05 00:52:44
你必须是。我使用gnuplot,需要查看文件等。 – 2010-11-05 00:58:48