7

我有一个程序可以生成大量数据并将其放入队列中以进行写入,但问题是它生成数据的速度比我当前正在写入的速度快(导致它达到最大内存并开始变慢)。顺序无关紧要,因为我打算稍后解析文件。

我环顾四周,发现了一些帮助我设计当前流程的问题(但我仍然觉得它很慢)。到目前为止,这是我的代码:

//...background multi-threaded process keeps building the queue..
FileWriter writer = new FileWriter("foo.txt",true);
        BufferedWriter bufferWritter = new BufferedWriter(writer);
        while(!queue_of_stuff_to_write.isEmpty()) {
            String data = solutions.poll().data;
            bufferWritter.newLine();
            bufferWritter.write(data);
        }
        bufferWritter.close();

我对编程很陌生,所以我可能会评估这个错误(可能是我使用 EC2 时的硬件问题),但是是否可以非常快速地将队列结果转储到文件中,或者如果我的方法还可以,我可以改进它吗不知何故?由于顺序无关紧要,写入多个驱动器上的多个文件是否更有意义?线程会使它更快吗?等等。我不确定最好的方法,任何建议都会很棒。我的目标是保存队列的结果(抱歉没有输出到 /dev/null :-) 并让我的应用程序的内存消耗尽可能低(我不是 100% 确定,但队列填满了 15gig,所以我'我假设它将是一个 15gig+ 文件)。

在文本文件 Java 中写入大量数据的最快方法(意识到我应该使用缓冲写入器) 在 Windows 上用 Java 并发文件写入(让我看到多线程写入可能不是一个好主意)

4

4 回答 4

2

看着那段代码,我想到的一件事是字符编码。您正在编写字符串,但最终,它是流向流的字节。引擎盖下的写入器字符到字节编码,它在处理写入的同一线程中进行。这可能意味着有时间用于延迟写入的编码,这可能会降低写入数据的速率。

一个简单的更改是使用队列byte[]而不是String,在推送到队列的线程中进行编码,并让 IO 代码使用 aBufferedOutputStream而不是 a BufferedWriter

如果编码文本平均每个字符占用少于两个字节,这也可以减少内存消耗。对于拉丁文本和 UTF-8 编码,这通常是正确的。

但是,我怀疑您生成数据的速度可能比您的 IO 子系统处理它的速度更快。您将需要使您的 IO 子系统更快 - 通过使用更快的子系统(如果您在 EC2 上,可能租用更快的实例,或者写入不同的后端 - SQS、EBS 和本地磁盘等),或者通过组合几个 IO 子系统以某种方式并行在一起。

于 2012-04-09T17:17:44.737 回答
1

是的,在多个驱动器上写入多个文件应该会有所帮助,如果没有其他东西同时写入这些驱动器,性能应该随着驱动器数量线性扩展,直到 I/O 不再是瓶颈。您还可以尝试其他一些优化来进一步提高性能。

如果您正在生成巨大的文件并且磁盘根本跟不上,您可以使用 GZIPOutputStream 来缩小输出——这反过来又会减少磁盘 I/O 的数量。对于非随机文本,您通常可以期望压缩比至少为 2x-10x。

    //...background multi-threaded process keeps building the queue..
    OutputStream out = new FileOutputStream("foo.txt",true);
    OutputStreamWriter writer = new OutputStreamWriter(new GZIPOutputStream(out));
    BufferedWriter bufferWriter = new BufferedWriter(writer);
    while(!queue_of_stuff_to_write.isEmpty()) {
        String data = solutions.poll().data;
        bufferWriter.newLine();
        bufferWriter.write(data);
    }
    bufferWriter.close();

如果您正在输出常规(即重复)数据,您可能还需要考虑切换到不同的输出格式——例如,数据的二进制编码。根据数据的结构,将其存储在数据库中可能更有效。如果您正在输出 XML 并且真的想坚持使用 XML,那么您应该研究二进制 XML格式,例如 EXI 或 Fast InfoSet。

于 2012-04-09T17:40:54.700 回答
0

我想只要您从计算中生成数据并且不从另一个数据源加载数据,写入总是比生成数据慢。

您可以尝试在多个线程中将数据写入多个文件(不在同一个文件中->由于同步问题)(但我想这不会解决您的问题)。

您是否可以等待应用程序的编写部分完成其操作并继续计算?

另一种方法是:你清空你的队列吗?Solutions.poll() 是否会减少您的解决方案队列?

于 2012-04-09T17:04:44.210 回答
0

使用多个线程写入不同的文件是一个好主意。此外,您应该考虑设置 BufferedWriters 缓冲区大小,您可以从构造函数中执行此操作。尝试使用 10 Mb 缓冲区进行初始化,看看是否有帮助

于 2012-04-09T17:11:23.817 回答