【问题标题】:Disk reading operation is performing very slow | Java Stream磁盘读取操作执行很慢 | Java 流
【发布时间】:2018-10-16 18:32:53
【问题描述】:

我需要从文件夹中读取图像并为它们生成校验和。大约有 330760 张图像。以下是代码:

package com.test;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import org.apache.commons.codec.digest.DigestUtils;

public class FileTest2 {

    private void readFiles() throws IOException {
        try (Stream<Path> filePathStream = Files
                .walk(Paths.get("d:\\codebase\\images"))) {
            filePathStream.parallel().forEach(filePath -> {
                String checksumSHA256 = "";
                try {
                    checksumSHA256 = DigestUtils.sha384Hex(new FileInputStream(filePath.toString()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (Files.isRegularFile(filePath)) {
                    System.out.println(checksumSHA256);
                    System.out.println(filePath);
                    System.out.println("\n");

                }
            });
        }
    }

    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        FileTest2 fileTest = new FileTest2();
        fileTest.readFiles();
        long endTime = System.currentTimeMillis();
        System.out.println("Total Time took: " + (endTime - startTime) / 1000);
    }
}

大约需要 36 分钟。

系统配置:

核心数:8
内存:32 GB(15-17 GB 是免费的)。其余内存正在被另一台服务器使用。

36 分钟太多了。有没有办法提高性能?

【问题讨论】:

  • 我可以看到文本文件中的所有条目/文件名路径似乎并没有花那么长时间。但是,代码仍在执行中。我想在这里关闭任何资源吗?
  • 您启动了一个线程池,它仍然处于活动状态,即使它无关。它只是坐在那里无所事事地等待工作。为什么要创建线程池?你的代码没有做任何多线程的事情。无论如何,关闭执行器。
  • 为什么你认为程序应该“占用所有内存”?你的程序什么也没做。 --- 为什么你创建了一个关于代码慢的问题,然后实际上没有询问慢代码,甚至显示它很慢?请编辑问题并清理它!!!
  • 是的。我错过了关闭执行者。
  • 你为什么要测试Files.isRegularFile(filePath) 你已经计算了它的校验和?现在质疑那个属性是不是有点晚了?除此之外,使用 parallel 流执行三个单独的打印语句并不是一个好主意,因为每个其他线程都可以在其间执行自己的打印语句。此外,你为什么要走旧的 I/O 弯路,即 new FileInputStream(filePath.toString()) 而不是使用 Files.newInputStream(filePath)

标签: java performance java-8 java-stream filestream


【解决方案1】:

正如其他人指出的那样,您不会终止执行者。要查看实际时间,请运行以下命令

public static void main(String[] args) throws Exception {
    long startTime = System.currentTimeMillis();

    FileTest fileTest = new FileTest();
    fileTest.readFiles();

    long endTime = System.currentTimeMillis();
    System.out.println("Total Time took: "+ (endTime-startTime)/1000);
}

注意:至少从您发布的代码来看,没有理由使用ExecutorService

【讨论】:

  • 刚刚更新了我的代码。为所有图像生成校验和。
  • 请运行我建议的代码并报告“所用总时间:”的值
  • 我刚刚完成了并行操作,耗时:2086 秒。 filePathStream.parallel().forEach(filePath -> {} 尚未尝试不使用并行,但我敢肯定这会很糟糕,
  • 请注释掉 println 语句并报告“总时间花费:”的值
  • 此外,通过 sha 的实现,您不仅可以测量遍历文件系统所需的时间,还可以测量读取每个文件所需的时间
猜你喜欢
  • 2019-12-11
  • 2018-01-27
  • 1970-01-01
  • 2015-07-07
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多