澄清线程性能处理1000的日志文件

时间:2013-09-20 14:07:23

标签: java multithreading performance executorservice

我从日志文件中提取出匹配模式的行。因此,我将每个日志文件分配给Runnable对象,该对象将找到的模式行写入结果文件。 (同步写作方法很好)

正在讨论的重要摘要:

ExecutorService executor = Executors.newFixedThreadPool(NUM_THREAD);


for (File eachLogFile : hundredsOfLogFilesArrayObject) {
executor.execute(new RunnableSlavePatternMatcher(eachLogFile));
}

重要标准:

日志文件的数量可能非常少,如20或某些用户的日志文件数量可能超过1000.我在excel表中记录了一系列测试,我真的很担心RED标记的结果。

1.我假设如果创建的线程数等于要处理的文件数,那么与线程数小于线程数的情况相比,处理时间会更短。未处理的待处理文件数。 (如果我的理解错误,请告诉我)

结果:

Result

  1. 我想确定NUM_THREAD的值,该值对于较少数量的文件以及1000个文件是有效的
  2. 建议我回答问题1& 2

    谢谢! Chandru

5 个答案:

答案 0 :(得分:3)

您刚刚发现您的程序不受CPU限制,但(可能)IO绑定

这意味着超过10个线程,操作系统无法跟上所有需要读取数据的线程,而且更多线程一次等待下一个数据块

也因为编写输出在所有线程中同步,甚至可能是程序中最大的瓶颈,(生产者 - 消费者解决方案可能是最小化线程等待输出的时间的答案)

最佳线程数取决于您读取文件的速度(读取线程越多越有用),

答案 1 :(得分:2)

看来2个线程就足以使用你所有的处理能力了。很可能你有两个内核和超线程。

  

我的是Intel i5 2.4GHz 4CPU 8GB Ram。这个细节有用吗?

根据型号的不同,它有2个内核和超线程。

  

我假设如果创建的线程数等于要处理的文件数,则处理时间会更短,

这将最大限度地增加开销,但不会给你更多的内核。

答案 2 :(得分:1)

并行化时,使用比可用cpu内核多得多的线程通常会增加总时间。你的系统将花费一些开销时间在一个cpu核心上从一个线程切换到一个线程,而不是一次又一个地执行任务。

如果你的计算机上有8个cpu核心,你可能会看到使用8/9/10线程而不是仅使用1个线程的一些改进,而使用20+线程实际上效率会降低。

答案 3 :(得分:1)

一个问题是I / O没有很好地并行化,特别是如果你有非SSD,因为顺序读取(当一个线程读取文件时会发生什么)比随机读取快得多(当读取头有时)在几个线程读取的不同文件之间跳转)。我猜你可以通过从发送作业到执行程序的线程中读取文件来加速程序:

for (File file : hundredsOfLogFilesArrayObject) {
    byte[] fileContents = readContentsOfFile(file);
    executor.execute(new RunnableSlavePatternMatcher(fileContents));
}

至于最佳线程数,取决于。

如果您的应用程序受I / O限制(如果您没有对内容进行极其繁重的处理,那很可能),可以在原始线程读取下一个文件时处理文件内容的单个工作线程可能就足够了。

如果你受CPU限制,你可能不需要比你有核心更多的线程:

ExecutorService executor = Executors.newFixedThreadPool(
    Runtime.getRuntime().availableProcessors());

虽然,如果你的线程被挂起很多(等待同步锁或其他东西),你可以通过更多的线程获得更好的结果。或者,如果你正在进行其他CPU咀嚼活动,你可能需要更少的线程。

答案 4 :(得分:0)

您可以尝试使用缓存的线程池。

public static ExecutorService newCachedThreadPool()

创建一个根据需要创建新线程的线程池,但在它们可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,调用执行将重用先前构造的线程。

您可以阅读更多here