2013-03-16 132 views
0

我正在开发一个项目,其中需要测量程序所花费的总时间和程序所花费的平均时间。该程序是一个多线程程序。总共花费的时间和所有线程所花费的平均时间

在该程序中,每个线程都在特定范围内工作。输入参数是Number of ThreadsNumber of Task

如果number of threads is 2number of tasks is 10那么每个线程将执行10 tasks。所以这意味着2线程将做20 tasks

使指─

第一线应使用1 and 10及第二线程之间的ID应该是使用11 and 20之间的ID。

我得到了上述方案的工作。现在我想测量所有线程所花费的总时间和平均时间。所以我在我的程序中得到了下面的设置。

问题陈述: -

谁能告诉我我将尝试所有的线程来衡量Total time and Average time taken的方法是在我下面的程序正确与否?

//create thread pool with given size 
ExecutorService service = Executors.newFixedThreadPool(noOfThreads); 

long startTime = 0L; 
try { 

    readPropertyFiles(); 

    startTime = System.nanoTime(); 

    // queue some tasks 
    for (int i = 0, nextId = startRange; i < noOfThreads; i++, nextId += noOfTasks) { 

     service.submit(new XMPTask(nextId, noOfTasks, tableList)); 
    } 

    service.shutdown(); 
    service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 

} finally { 
    long estimatedTime = System.nanoTime() - startTime; 
    logTimingInfo(estimatedTime, noOfTasks, noOfThreads); 
} 



private static void logTimingInfo(long elapsedTime, int noOfTasks, int noOfThreads) { 

    long timeInMilliseconds = elapsedTime/1000000L; 
    float avg = (float) (timeInMilliseconds)/noOfTasks * noOfThreads; 

    LOG.info(CNAME + "::" + "Total Time taken " + timeInMilliseconds + " ms. And Total Average Time taken " + avg + " ms"); 
} 

回答

0

service.submit是越来越只执行noOfThreads倍。 XMPTask对象创建次数相同。

0

您测量的时间不是消耗的时间时间,但时间过去了时间。

如果测试的程序(JVM)是​​计算机上唯一的一个,它可能相对准确,但在现实世界中,许多进程并行运行。

我已经完成了这项工作,使用本地调用操作系统,在Windows上(我将在周一完成这篇文章在我的办公室)和Linux(/ proc)。

+0

仅供参考,上面的程序,我将运行在一台专门用于我们的LNP测试的机器上。 – AKIWEB 2013-03-16 21:07:09

0

我认为你需要测量任务类本身的时间(XMPTask)。在该任务中,您应该能够提取正在执行它的线程的标识并将其记录下来。使用这种方法将需要读取日志并对它们进行一些计算。

另一种方法是随着时间的推移保持运行总计和平均值。要做到这一点,你可以编写一个简单的类,传递给每个具有一些静态(每个jvm)变量的任务,以跟踪每个线程正在做什么。然后你可以在线程池之外有一个线程进行计算。所以如果你想每秒钟报告每个线程的平均CPU时间,这个计算线程可以休眠一秒钟,然后计算并记录所有的平均时间,然后睡眠一秒钟... ...

编辑:After重新阅读要求,你不需要后台线程,但不知道我们是否跟踪每个线程的平均时间或每个任务的平均时间。我假定每个线程的总时间和平均时间,并在下面的代码中充实了这个想法。它没有被测试或调试,但应该给你如何开始一个好主意:

public class Runner 
{ 
    public void startRunning() 
    { 
     // Create your thread pool 
     ExecutorService service = Executors.newFixedThreadPool(noOfThreads); 

     readPropertyFiles(); 

     MeasureTime measure = new MeasureTime(); 

     // queue some tasks 
     for (int i = 0, nextId = startRange; i < noOfThreads; i++, nextId += noOfTasks) 
     { 

      service.submit(new XMPTask(nextId, noOfTasks, tableList, measure)); 
     } 

     service.shutdown(); 
     service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
     measure.printTotalsAndAverages(); 
    } 
} 

public class MeasureTime 
{ 
    HashMap<Long, Long> threadIdToTotalCPUTimeNanos = new HashMap<Long, Long>(); 
    HashMap<Long, Long> threadIdToStartTimeMillis = new HashMap<Long, Long>(); 
    HashMap<Long, Long> threadIdToStartTimeNanos = new HashMap<Long, Long>(); 

    private void addThread(Long threadId) 
    { 
     threadIdToTotalCPUTimeNanos.put(threadId, 0L); 
     threadIdToStartTimeMillis.put(threadId, 0L); 
    } 

    public void startTimeCount(Long threadId) 
    { 
     synchronized (threadIdToStartTimeNanos) 
     { 
      if (!threadIdToStartTimeNanos.containsKey(threadId)) 
      { 
       addThread(threadId); 
      } 

      long nanos = System.nanoTime(); 
      threadIdToStartTimeNanos.put(threadId, nanos); 
     } 
    } 

    public void endTimeCount(long threadId) 
    { 
     synchronized (threadIdToStartTimeNanos) 
     { 
      long endNanos = System.nanoTime(); 
      long startNanos = threadIdToStartTimeNanos.get(threadId); 

      long nanos = threadIdToTotalCPUTimeNanos.get(threadId); 
      nanos = nanos + (endNanos - startNanos); 
      threadIdToTotalCPUTimeNanos.put(threadId, nanos); 
     } 
    } 

    public void printTotalsAndAverages() 
    { 
     long totalForAllThreadsNanos = 0L; 
     int numThreads = 0; 
     long totalWallTimeMillis = 0; 
     synchronized (threadIdToStartTimeNanos) 
     { 
      numThreads = threadIdToStartTimeMillis.size(); 
      for (Long threadId: threadIdToStartTimeNanos.keySet()) 
      { 
       totalWallTimeMillis += System.currentTimeMillis() - threadIdToStartTimeMillis.get(threadId); 
       long totalCPUTimeNanos = threadIdToTotalCPUTimeNanos.get(threadId); 

       totalForAllThreadsNanos += totalCPUTimeNanos; 
      } 
     } 

     long totalCPUMillis = (totalForAllThreadsNanos)/1000000; 
     System.out.println("Total milli-seconds for all threads: " + totalCPUMillis); 
     double averageMillis = totalCPUMillis/numThreads; 
     System.out.println("Average milli-seconds for all threads: " + averageMillis); 

     double averageCPUUtilisation = totalCPUMillis/totalWallTimeMillis; 
     System.out.println("Average CPU utilisation for all threads: " + averageCPUUtilisation); 
    } 
} 

public class XMPTask implements Callable<String> 
{ 
    private final MeasureTime measure; 

    public XMPTask(// your parameters first 
      MeasureTime measure) 
    { 
     // Save your things first 

     this.measure = measure; 
    } 

    @Override 
    public String call() throws Exception 
    { 
     measure.startTimeCount(Thread.currentThread().getId()); 

     try 
     { 
      // do whatever work here that burns some CPU. 
     } 
     finally 
     { 
      measure.endTimeCount(Thread.currentThread().getId()); 
     } 

     return "Your return thing"; 
    } 
} 

写这毕竟,有一两件事似乎是一个有点奇怪的XMPTask似乎知道太多关于任务列表,我想你应该为每个任务创建一个XMPTask,给它足够的信息来完成这项工作,并在创建它们时将它们提交给服务。

+0

感谢hack_on的建议。你的第二种方法是一个好主意。你能否为我提供第二种方法的简单例子?谢谢您的帮助。 – AKIWEB 2013-03-16 21:17:22