美文网首页
Java内存优化之POI Excel(二)

Java内存优化之POI Excel(二)

作者: jarvan4dev | 来源:发表于2017-11-16 20:56 被阅读159次

    问题背景及排查:Java内存优化之POI Excel(一)
    其实除了内存调整,还做了策略上的调整,既然创建一整个数十万行的Excel比较耗内存,那我就分片创建呗,所谓分片就是将一个大的Excel分成几个小的Excel,然后打成Zip。

    分片创建Excel

    Talk is cheap, show me the code!

    public String export() throws Exception {
            List<String> excelFileSplices = Lists.newArrayList();
            if (pageable) {
                // 可以分成几个Excel
                int pageCount = this.dataList.size() / PER_SPLICE_SIZE + 1;
                int index = 0;
                while (index < pageCount) {
                    List<T> dataSplices = this.dataList.subList(index * PER_SPLICE_SIZE,
                            Math.min(this.dataList.size(), (index + 1) * PER_SPLICE_SIZE));
                    String fileName = exportOne(dataSplices);
                    excelFileSplices.add(fileName);
                    index++;
                }
            } else {
                String fileName = exportOne(this.dataList, ignoredProperties);
                excelFileSplices.add(fileName);
            }
    
            log.info(excelFileSplices);
    
            if (excelFileSplices.size() == 1) {
                return excelFileSplices.get(0);
            } else {
                String zipFilePath = TMP_FILE + "/" + UUID.randomUUID().toString() + ".zip";
                ZipArchiveOutputStream zipArchiveOutputStream = null;
                InputStream is = null;
                try {
                    zipArchiveOutputStream = new ZipArchiveOutputStream(new File(zipFilePath));
                    zipArchiveOutputStream.setUseZip64(Zip64Mode.AsNeeded);
                    for (String srcFilePath : excelFileSplices) {
                        File sourceFile = new File(srcFilePath);
                        ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(sourceFile, sourceFile.getName());
                        zipArchiveOutputStream.putArchiveEntry(zipArchiveEntry);
                        is = new BufferedInputStream(new FileInputStream(sourceFile));
                        IOUtils.copy(is, zipArchiveOutputStream);
                        sourceFile.delete();
                    }
                    zipArchiveOutputStream.closeArchiveEntry();
                } finally {
                    IOUtils.closeQuietly(is);
                    IOUtils.closeQuietly(zipArchiveOutputStream);
                }
                return zipFilePath;
            }
        }
    

    其实策略实现比较简单,就是将数据全部撸到内存(其实这些数据也占不了多少内存,只是创建Excel的时候消耗了大量内存),然后在内存分页,分别创建Excel,最后将Excel达成Zip包上传到七牛。

    不妥协的DaYe

    WO: 以后下载清单会是压缩包了,会麻烦一点点...
    DaYe:我们要这个就是为了简单吗 ,你还麻烦一点 ,你怎么好意思说啊...
    WO: ......
    

    不说了,继续改吧。

    可见的效果

    其实这种性能优化,最讨厌感觉上优化了,明明做了啊,但是到底优化了多少,是一点点,还是很多,还是适得其反呢?怎么能做到心中没点B数。

    神奇的JConsole

    Sun真是良心,除了JDK,还提供了很多很好的附加工具,还说只是试验品,软件附加的,但是其实很好用,而且很稳定。

    什么是JConsole呢?在终端(Mac或者Windows)上输个jconsole就能看到,如图

    image.png

    图中com.zuihuibao.excel.ExcelOperator 34890是我启动的程序,可以选中它,然后连接。

    image.png

    点击不安全的连接,就可以看到各种你想看到的数据,比如当前内存大小内存峰值等,我打算用它来测量我优化的实际效果。

    image.png

    PS,可能第一次你一直连不上,请在你的启动程序上加个参数
    -Djava.rmi.server.hostname=localhost

    image.png

    相关文章

      网友评论

          本文标题:Java内存优化之POI Excel(二)

          本文链接:https://www.haomeiwen.com/subject/acbxmxtx.html