使用commons-compress优化zip打包性能

822 阅读1分钟

前言

最近有个需求需要将批量生成二维码并打包,业务逻辑开发完成后,测试发现打包过程比较慢,100个二维码达成压缩包需要3-5s。于是想使用多线程来打包,于是就发现commons-compress有现成的多线程打包方案。

原始方案压缩

/**
 * 压缩文件
 *
 * @param out          压缩文件夹输出流
 * @param inputStream  需要压缩的数据
 * @param zipEntryName 单项文件名称
 */
public static void put(ZipOutputStream out, InputStream inputStream, String zipEntryName) throws IOException {
    out.putNextEntry(new ZipEntry(zipEntryName));
    int len;
    byte[] buffer = new byte[2048];
    while ((len = inputStream.read(buffer)) > 0) {
        out.write(buffer, 0, len);
    }
    out.closeEntry();
}

直接使用ZipOutputStream进行打包二维码图片

原始apache-compress压缩

引入依赖

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-compress</artifactId>
  <version>1.21</version>
</dependency>

压缩方法

public static void compressTaskList(OutputStream outputStream, List<CustomFutureTask<Tuple2<BufferedImage, String>>> futureTaskList) throws Exception {
    ParallelScatterZipCreator parallelScatterZipCreator = new ParallelScatterZipCreator(EXECUTOR);
    ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(outputStream);
    zipArchiveOutputStream.setEncoding(StandardCharsets.UTF_8.name());
    for (int i = 0; i < futureTaskList.size(); i++) {
        final Tuple2<BufferedImage, String> image = futureTaskList.get(i).get();
        final InputStreamSupplier inputStreamSupplier = () -> bufferedImageToInputStream(image.getT1());
        ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(image.getT2());
        zipArchiveEntry.setMethod(ZipArchiveEntry.DEFLATED);
        zipArchiveEntry.setUnixMode(UnixStat.DEFAULT_FILE_PERM);
        parallelScatterZipCreator.addArchiveEntry(zipArchiveEntry, inputStreamSupplier);
    }
    parallelScatterZipCreator.writeTo(zipArchiveOutputStream);
    zipArchiveOutputStream.close();
    outputStream.close();
}

结果

通过优化后压缩提高很多,基本是秒下,感觉不到延迟。