有没有一种方法可以在Java中进行并行压缩?
我目前正在使用ParallelScatterZipCreator
,但不幸的是它只能按文件进行并行压缩。因此,如果有一个比其他文件大得多的单个文件,则并行压缩仅针对较小的文件进行。然后它必须等待直到大文件被串行压缩。
是否有更好的库可以利用所有CPU核心,即使我们正在压缩单个文件?
有没有一种方法可以在Java中进行并行压缩?
我目前正在使用ParallelScatterZipCreator
,但不幸的是它只能按文件进行并行压缩。因此,如果有一个比其他文件大得多的单个文件,则并行压缩仅针对较小的文件进行。然后它必须等待直到大文件被串行压缩。
是否有更好的库可以利用所有CPU核心,即使我们正在压缩单个文件?
因为zip在每个文件上“重新启动”压缩窗口。这是低效的,会损害zip文件的压缩比。
如果需要的话,你可以将相同的原则应用于任何数据块。牺牲压缩效率以实现并行处理。ZIP格式不会以有用的方式执行此操作;正如你所说,如果只有一个更大的文件,则无意义。
'重新启动窗口'是一种可概括的原则,各种压缩格式支持以更有用的方式进行(每X字节重新启动,而不是ZIP的不可靠的“每个文件重新启动”)。
发送数据涉及多个方面:源提供要发送的字节的速度、将字节处理为可发送的包的速度(例如zip工具,但可以是任何内容,包括直接发送未压缩的数据),打包字节传输到目标系统的速度、目标系统解包的速度以及目标系统处理解包后结果的速度。
你确定压缩方面是瓶颈吗?
在基本情况下,从硬盘读取字节,将其压缩成zip格式,通过住宅互联网管道发送到另一个系统,该系统解压缩并将其保存在硬盘上,很可能瓶颈是网络。并行化压缩步骤是完全浪费的,事实上只会通过降低压缩比而减慢速度。
如果你从旋转盘中读取文件,则速度较慢的源很可能是瓶颈,而并行处理大大减慢速度:现在你要求读头来回跳动,这比一次顺序读取数据要慢得多。
如果你有快速的源和高速的传输管道,那么瓶颈无疑是压缩和解压缩,但解决方案不是压缩:根本不需要压缩:如果你正在从SSD或USB3连接的字节喷出传感器中传输数据,并将其从一个千兆以太网口传输到另一个千兆以太网口的10M CAT6电缆上,则为什么要进行压缩?只需发送这些字节即可。压缩不会使传输速度更快,只要不饱和1Gb连接,尝试对其进行压缩就完全没有任何收益。
如果你的传输管道速度很慢,那么使它更快的唯一方法就是尽可能多地压缩。这绝对不涉及使用DEFLATE算法(例如不要使用zip)。使用另一种算法,并将其配置为获得更好的压缩率,以牺牲CPU性能。并行化是无关紧要的;它不是瓶颈,因此完全没有必要这样做。
很可能您希望以未压缩的方式发送文件,或者使用ZStandard对文件进行压缩,并根据需要调整压缩与速度之间的比率。我不知道Java本身是否有任何ZStandard(zstd)实现,但是zstd-jni项目为您提供了一个基于Java的API,可调用C zstd库。
如果您坚持使用ZIP,则答案是相当基本的“不行”,尽管您可以理论上编写一个并行ZIP压缩器,其压缩能力更差但并行性更好(通过在单个文件中重启窗口以处理较大文件,并在每个文件结束时执行强制执行的重新启动),并且生成的ZIP文件仍然与全球几乎所有解压工具兼容。我不知道有没有这样一个压缩器,我认为没有,自己编写会是一个明显不简单的练习。