2013-03-16 181 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