3

我试图 gzip 一个大(100mb 到 500mb)的 xml 文件。我已经创建了方法 Zip 来做到这一点。问题是它谈论太多时间来压缩。对于 200mb 需要 1.2 秒。对于 100mb xml 文件,我需要将时间减少 100 毫秒。如何优化以减少压缩时间?

我通过在压缩比上几乎没有妥协来减少时间。尝试了另一种算法,如 Snappy、Lz4,但没有太大改进,而且它们的压缩率也很差。据我所知,gzipOutputStream.write() 需要 85% 的时间。所以我怎样才能优化这一步以获得更好的性能而不会影响很多压缩率。

public static String zip(final String str) {
    if ((str == null) || (str.length() == 0)) {
        throw new IllegalArgumentException("Cannot zip null or empty string");
    }

    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(str.length())) {
        try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream){{def.setLevel(Deflater.BEST_SPEED );}};) {
            gzipOutputStream.write(str.getBytes(StandardCharsets.UTF_8));

        } 
            T5 = System.currentTimeMillis();
            byte[] bytes=byteArrayOutputStream.toByteArray();
             T3 = System.currentTimeMillis();

            String zipped_text=DatatypeConverter.printBase64Binary(bytes);
             T4 = System.currentTimeMillis();
            return zipped_text;

    } catch(IOException e) {
        throw new RuntimeException("Failed to zip content", e);
    }

}
4

1 回答 1

1

这是我的建议:

  1. 创建一个适当的基准,以便您可以获得可重复的结果。我建议使用基准测试框架;例如 JMH。

  2. 分析您的代码/基准,以确定瓶颈/热点在哪里;例如使用 jVisualVM 或 Java Mission Control Flight Recorder。

  3. 使用基准和分析结果来指导您的优化工作。

System.currentTimeMillis()(出于各种原因,我不会仅仅依靠调用。)

一种可能的解释是,在以下步骤中,大部分时间都花在了数据复制上。

  • 创建包含 XML 的输入字符串
  • 捕获压缩字节ByteArrayOutputStream
  • 将字节协调到另一个字符串中。

因此,如果您正在寻找改进这一点的方法,请尝试安排一些事情,以便 XML 序列化程序写入通过 gzip 和 base64 转换流式传输数据的管道,然后直接写入文件或套接字流。

另外,如果可能的话,我会避免使用 base64。如果压缩的 XML 在 HTTP 响应中,您应该能够以二进制形式发送它。它会更快,并产生更少的网络流量。

最后,选择一种在压缩率和压缩时间之间取得良好折衷的压缩算法。


如何在不影响压缩比的情况下优化此步骤以获得更好的性能。

如果你试图这样做,你的目标可能是错误的。(为什么你然后对压缩文件进行 Base64 编码?这与你的目标相矛盾!)


更新以解决您的评论:

  1. 与将 XML 转换为字符串然后调用getBytes()它相比,您将(我认为)通过流式传输获得更好的性能。首先,getBytes()调用是对字符串内容进行不必要的复制。

  2. 关于无损压缩的维基百科页面链接到许多算法,其中许多应该有现成的 Java 实现。此外,它还链接到许多基准。我没有查看基准链接,但我希望至少有一个可以量化不同算法的压缩与计算时间的权衡。

  3. 如果将数据库表从 CLOB 更改为 BLOB:

    • 您可以省去 base64,节省约 25% 的存储空间
    • 您可以省去 base64 编码步骤,节省百分之几的 CPU
    • 然后,您可以选择一个更快(但不太紧凑)的算法,以牺牲您通过 BLOB 节省的一些空间为代价节省更多时间。
  4. “我无法真正改变它的业务需求。” - 真的?如果数据库模式是业务需求,那么您的业务确实出了问题。另一方面,如果业务在该级别决定技术,那么他们也在决定性能。

    将压缩数据存储为 CLOB 没有合理的技术理由。

  5. 正如有人指出的,获得更快压缩的最简单方法是购买速度更快的计算机。或者(我的想法)一组计算机,以便您可以并行压缩多个文件。

于 2019-05-06T12:10:56.290 回答