繁体   English   中英

将大数据保存到文件的最快方法

[英]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行。 这引出了我的问题:

  1. c ++示例可以更快吗?
  2. 我应该使用StringBuilder for Java还是因为行数而导致它也很糟糕
  3. 还有其他方式或图书馆吗?
  4. C#怎么样?

谢谢

简介它。 运行代码,计时,看看需要多长时间。 如果花费的时间是可以接受的,请使用它。 如果没有,弄清楚哪个部分需要花费很长时间才能运行,并对其进行优化。

  • 改正它。
  • 快一点。

那个命令。 (有些人在这两个之前添加“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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM