如何让Java使用我的多核处理器和GZIPInputStream?

时间:2010-01-01 21:08:38

标签: java parallel-processing gzip multicore gzipinputstream

我在我的程序中使用GZIPInputStream,我知道如果我可以让Java并行运行我的程序,性能会有所帮助。

通常,是否有标准VM的命令行选项可以在许多核心上运行?它只运行一个。

谢谢!

修改

我正在Windows XP上运行普通的'Java SE 6更新17。

将GZIPInputStream放在一个单独的线程上会显式帮助吗?不!不要将GZIPInputStream放在单独的线程上!不要多线程I / O!

编辑2

我认为I / O是瓶颈,因为我正在读写同一个磁盘......

总的来说,有没有办法让GZIPInputStream更快?或者是并行运行的GZIPInputStream的替代品?

编辑3 我使用的代码段:

GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(INPUT_FILENAME));
DataInputStream in = new DataInputStream(new BufferedInputStream(gzip));

9 个答案:

答案 0 :(得分:16)

AFAIK从此流中读取的操作是单线程的,因此如果您正在读取一个文件,则多个CPU将无法帮助您。

但是,您可以拥有多个线程,每个线程都解压缩不同的文件。

话虽如此,解压缩目前并不是特别严密的计算,你更有可能被IO的成本所阻挡(例如,如果你在HD的两个不同区域读取两个非常大的文件)。 / p>

更一般地说(假设这是Java新手的问题),Java不会为您并行做事。您必须使用线程来告诉它您要执行的工作单元以及如何在它们之间进行同步。 Java(在操作系统的帮助下)通常会占用尽可能多的内核,并且如果线程多于内核(通常是这种情况),也会在同一内核上交换线程。

答案 1 :(得分:6)

PIGZ = GZip的并行实现是gzip的全功能替代品,它在压缩数据时利用多个处理器和多个核心。 http://www.zlib.net/pigz/它还不是Java--任何接受者。当然,世界需要Java。

有时压缩或解压缩是一个很大的CPU用户,尽管它有助于I / O不成为瓶颈。

另请参阅HP Labs的数据库(C ++)。 PIGZ仅对压缩进行并行化,而Dataseries将输出分解为大型压缩块,这些块可并行解压缩。还有许多其他功能。

答案 2 :(得分:2)

将GZIP流包装在缓冲流中,这样可以显着提高性能。

OutputStream out = new BufferedOutputStream(
    new GZIPOutputStream(
        new FileOutputStream(myFile)
    )
)

同样对于输入流。使用缓冲的输入/输出流可减少磁盘读取次数。

答案 3 :(得分:2)

我没有看到解决程序的其他处理的任何答案。

如果您只是解压缩文件,最好只使用命令行gunzip工具;但是很可能会有一些处理正在处理您从该流中提取的文件。

如果你正在提取合理大小的块,那么你对这些块的处理应该在解压缩的单独线程中进行。

您可以在每个大字符串或其他数据块上手动启动一个线程;但是从Java 1.6开始,你会更好地使用java.util.concurrent中的一个奇特的新类,例如ThreadPoolExecutor


<强>更新

我不清楚问题和其他评论是否真的只是使用Java提取文件。如果你真的认为你应该尝试与gunzip竞争,那么你可以通过使用大缓冲来获得一些性能;也就是说,使用10 MB的缓冲区(二进制,而不是十进制! - 1048576),将其填入单个gulp并同样写入磁盘。这将使您的操作系统有机会对磁盘空间进行一些中等规划,并且您也需要更少的系统级调用。

答案 4 :(得分:0)

压缩似乎是并行化的一个难题,因为压缩器发出的字节是前一个W字节输入的非平凡函数,其中W是窗口大小。显然,您可以将文件分成几部分,并为在自己的线程中运行的每个部分创建独立的压缩流。您可能需要保留一些压缩元数据,以便解压缩程序知道如何将文件重新组合在一起。

答案 5 :(得分:0)

使用gzip进行压缩和解压缩是一个序列化过程。要使用多个线程,您必须创建一个自定义程序,将输入文件分解为多个流,然后使用自定义程序将其解压缩并将它们连接在一起。无论哪种方式,在使用CPU之前,IO都将成为一个瓶颈。

答案 6 :(得分:0)

运行多个VM。每个VM都是一个进程,您应该能够为每个核心运行至少三个进程,而不会降低性能。当然,您的应用程序必须能够利用多处理才能获益。没有灵丹妙药,这就是为什么你看到媒体上的文章呻吟着我们还不知道如何使用多核机器。

然而,有很多人将他们的应用程序结构化为一个管理工作流程池并将工作包分发给他们的主服务器。并非所有问题都可以通过这种方式解决。

答案 7 :(得分:0)

我认为假设多线程IO 总是邪恶是错误的。您可能需要确定您的具体案例,因为:

  • 最近的操作系统使用当前可用的内存用于缓存,当您阅读它们时,您的文件实际上可能不在硬盘上。
  • 最新的硬盘驱动器(如SSD)的访问时间要快得多,因此更改阅读位置的问题要小得多。
  • 这个问题太笼统,不能假设我们正在阅读单个硬盘。

您可能需要调整读取缓冲区,使其足够大以降低转换成本。在边界情况下,可以将所有文件读入内存并在那里并行解压缩 - 更快,并且IO多线程没有任何损失。然而,不太极端的东西也可能更好。

您也无需在JRE上使用多个可用内核做任何特殊操作。不同的线程通常会使用由操作系统管理的不同内核。

答案 8 :(得分:0)

您无法并行化标准GZipInputStream,它是单线程的,但是您可以管道进行解压缩并将处理后的流处理为不同的线程,即,将GZipInputStream设置为生产者以及将其作为消费者进行任何处理,并将它们与有限的阻塞队列连接。