我必须在10个大尺寸文件中搜索一个字符串(压缩格式为70 MB),并且必须将带有搜索字符串的行打印到相应的10个输出文件中。(即文件1输出应该在output_file1中... file2 ---> output_file2)。对于单个文件,相同的程序需要15分钟。但如果使用10个线程来读取10个文件并写入10个不同的文件,它应该在15分钟内完成,但需要40分钟。
我该如何解决这个问题。或多线程只需要这么多时间?
答案 0 :(得分:5)
并发访问文件通常在2-3个线程之后变慢,因为硬盘最终会同时尝试从所有文件中读取数据,类似于读取碎片整理文件。
要避免这种情况,请将工作拆分为文件读取器和文件解析器。文件读取器从文件中引入数据(也解压缩),文件解析器解析数据。您可以使用PipedInputStream
/ PipedOutputStream
将文件读取器中的数据转发到文件解析器。
因为您的文件是压缩的,所以读取涉及I / O和cpu,它们可以在2-4个读取所有文件的线程中很好地交错。对于解析文件,最简单的方法就是只从PipedInputStream中读取一个线程,这样每个文件就有一个解析器线程。每个文件使用多个线程需要拆分流并处理块边界处的搜索,这会使进程复杂化,这里不需要,因为您可能有足够的并行性来处理10个解析器线程和2-4个读取器线程。
答案 1 :(得分:4)
我想你没有使用10-core-cpu-machine所以你的线程并没有真正并行运行。因此它需要比数学上更长的时间。接下来的事情是你必须要知道线程管理也需要一些时间(这是无关紧要的)。 也许你可以加快文件的搜索机制,以获得一些速度。为此,您需要发布您的源代码。 但有些人建议:
但请注意,这些措施可能导致一个非常复杂的代码供另一个人或你自己阅读...让我们说六个月+因为你不记得你做过的一切以及你为什么这样做(评论;) )
答案 2 :(得分:0)
您可能有硬盘争用,多线程无效。在您的情况下,您可能只需要足够的线程来保持磁盘驱动器100%的使用率。
我假设硬盘是你的瓶颈,而不是CPU。如果每个线程不必在相同的硬件上进行争夺,则多线程只会使事情“更快”完成。因此,使用多个内核(CPU)和多个硬盘驱动器,您将看到多线程的更好性能。
我很惊讶单个文件需要15分钟。
以下是我设计的方法。 70 MB并不大。您可以将每个70 MB未压缩文件加载到内存中,每个线程一个。然后,在搜索压缩流时实时解压缩数据,在内存中保留大量未压缩数据。 (一旦你搜索过它,扔掉它)。这样可以避免硬盘颠簸,让CPU达到100%的使用率。
如果内存有问题,请从磁盘一次加载几MB。
答案 3 :(得分:0)
由于您的瓶颈将是磁盘IO,因此更多线程很可能只会让它运行得更慢。如果你可以先将所有数据加载到内存中,那么你会看到一些从多个线程加速,但只到#cores + 1,更多的只是上下文切换开销。
答案 4 :(得分:0)
当你运行它时,你的CPU是否已经100%了?如果不是,那就是两件事之一;
答案 5 :(得分:0)
我猜这是一个GC问题。我猜你一次将这些文件读成String
。也许你甚至为每一行重新编译一个正则表达式。无论如何,大量的内存分配,但短暂的对象。多个线程可能会提示足够的内容以复制到“幸存者”空间(在典型的Sun GC实现中)。我想使用visualvm或一个模糊的命令行参数来监控GC的工作难度。
也可能是锁争用问题,但这看起来很尴尬。
答案 6 :(得分:0)
你可能想看看Tim Bray创建的the "Wide Finder"项目。这听起来非常像你正在做的事情,我认为检查大多数(如果不是所有)你将遇到的问题。 HTH