并行Java 8 Stream.filter()?

时间:2018-07-20 21:43:04

标签: java performance java-8 java-stream

我正在制作一个音乐转换程序,以自动进行许多琐碎的转换,并将大型音乐库转换为各种形式的.opus文件。 (诸如用于移动设备的比特率修改和元数据的自动生成之类的事情。)

我对一个特定的流(包含所有Path个音乐文件(这是一个非常大的流,因为音乐库往往很大))有问题,我目前需要经过两个步骤对所有库文件Path对象执行操作。

首先对它们进行过滤(以确保它们不存在于Converted文件夹中(如果这样做,它们将被跳过并且不通过转换器运行),然后对它们进行过滤。转换后的文件夹将转换为转换任务(Runnable/Callable)并提交到执行程序池。

我在过滤部分遇到了性能瓶颈。我已经从代码的角度运行了典型的性能分析/性能优化,但是从根本上来说,我必须执行的比较类型需要很长时间(它们是磁盘操作,调用了一个名为{{1的外部库}},以获取和比较文件元数据)。这些过程需要一段时间,但是它们都由Netbeans探查器上的exiftool线程来运行。

TL; DR伪代码:

Main

如何通过使用多于Stream<Path> stream = ... stream.filter(path -> exiftoolFilter(path)).forEach(path -> convert(path)); 的线程来切换到Main来优化过滤性能?我当时在考虑使用分离器,但从未使用过分离器,而对({http://www.baeldung.com/java-spliterator)等教程的分离器工作方式只有最模糊的表示。我希望保留在Java8.Streams API中。

您可以显示一个实现示例(甚至是伪代码)吗?

如果有帮助,我正在Kubuntu 18.04上使用Java 8_171。 (Netbeans是Java发行版后面的一些整数版本,并且在将代码捐赠给Apache之后正在构建程序的较新版本)

修改0: 我已经考虑了性能。 我可以确定的主要性能瓶颈是来自文件路径遍历流的单个过滤器语句。

本质上是这样的:

forEach

其中:fileWalk(rootMusicDir).filter(path -> !(existInFolder(path) || filterByFileAttributes(path) || filterByFileName(path))) 是一个简短的函数,仅检查文件名是否已存在于“已经建立索引”文件夹中,existInFolder(Path)是一个运行时间很长的函数,它使用filterByFileAttributes(path)和视图文件的元数据以获取其属性:exiftool,并查看目录中是否存在Title.opus,filterByFileName(path)在文件名本身中查找模式,以查看是否可以将其分解,并查看是否目录中存在。

我们看到,只有当一个或多个内部函数调用为Title时,上述 overall 布尔语句才为false。这是有道理的,因为我们不想索引文件夹中已经存在的任何内容,并且仅当内部函数调用都不为真时才为真。 (注意:我不知道这是否是布尔运算的理想配置,只是由我组成的一种,可以产生适当的功能)

对于.opus文件,这样做有几个原因。 1)该程序的主要目的是保存尽可能多的元数据,因此不能复制/不进行复制。 2)音乐文件可以以至少两种不同的形式存在,例如:true,或者,完成后它应该只显示为SomeArtist -- SomeTrackTitle在磁盘上,并且其内部文件属性设置为{{ 1}}和SomeTrackTitle.opus。此功能还可以为整个移动设备库提供低比特率的副本。

作为参考,我说这个程序是一个转换器。它需要一些文件路径并将其转换为.opus文件。但是两个文件名可以不同。因此,我们可能会从Artist = SomeArtist-> Title=SomeTrackTitle进行转换,也可以是Artist -- Title(设置属性)-> Title.opus(设置属性,但比特率较低) ,此子例程是一个升级功能,用于将库的较旧版本升级为新的命名格式(在下文中提及)。因此它可能具有这些不同的名称,而所有输出只是Title

根据我记得的有关Java优化和布尔逻辑语句的内容,JVM将尝试短路任何布尔逻辑语句。我根据遇到每个函数将运行的情况的统计概率,将先前的Title.opus重新排序为其当前配置。在此之前,过去通常会先调用运行时间最长的函数,但现在情况已不再如此。使用889个文件,运行时间从10:00-> 00:59减少了。因此,还不错,但对于仅比较文件名也不好。

主要问题似乎是该程序的早期版本没有一致的命名方案,或者我认为名称会被更改(该程序的旧版本可以使用上述名称格式) 。我没想到会使用或设置.opus元数据,因为这似乎是不可能的。然后我意识到ffmpeg支持.opus,并找到了opusenc(Kubuntu的opus编码器)和exiftool(用于读取元数据)。由于我现在已经为该名称的文件格式进行了标准化,因此将来应该会更快。

0 个答案:

没有答案