0

プログラムにかかる合計時間とプログラムにかかる平均時間を測定する必要があるプロジェクトに取り組んでいます。そしてそのプログラムはマルチスレッドプログラムです。

そのプログラムでは、各スレッドが特定の範囲で動作しています。入力パラメータはNumber of ThreadsNumber of Taskです。

If number of threads is 2and number of tasks is 10then 各スレッドが実行され10 tasksます。つまり、2 つのスレッドが実行され20 tasksます。

ということは――

最初のスレッドは id betweenを使用し1 and 10、2 番目のスレッドは id between を使用する必要があります11 and 20

上記のシナリオが機能しました。ここで、すべてのスレッドにかかった合計時間と平均時間を測定したいと思います。だから私は私のプログラムで以下のセットアップを得ました。

問題文:-

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");
}
4

3 に答える 3

0

service.submitnoOfThreads何度も実行されています。XMPTaskオブジェクトは同じ回数作成されます。

于 2013-03-16T21:00:26.080 に答える
0

測定する時間は、消費時間ではなく経過時間です。

テストされたプログラム(JVM)がコンピューター上にある唯一のプログラムである場合、それは比較的正確かもしれませんが、現実の世界では多くのプロセスが同時に実行されます。

私はすでに、Windows(月曜日に私のオフィスでこの投稿を完了します)とLinux(/ proc)でOSへのネイティブ呼び出しを使用してこの仕事をしました。

于 2013-03-16T21:01:03.700 に答える
0

タスククラス自体(XMPTask)内の時間を測定する必要があると思います。そのタスク内で、それを実行しているスレッドのIDを抽出し、それをログに記録できるはずです。このアプローチを使用するには、ログを読み取り、ログに対していくつかの計算を行う必要があります。

もう1つのアプローチは、時間の経過とともに現在の合計と平均を維持することです。これを行うには、各スレッドが実行していることを追跡するための静的(jvmごと)変数を持つ各タスクに渡される単純なクラスを作成できます。次に、計算を行ったスレッドプールの外部に単一のスレッドを作成できます。したがって、各スレッドの平均CPU時間を毎秒報告する場合、この計算スレッドは1秒間スリープしてから、すべての平均時間を計算してログに記録し、次に1秒間スリープすることができます。

編集:要件を読み直した後、バックグラウンドスレッドは必要ありませんが、スレッドごとの平均時間を追跡しているのか、タスクごとの平均時間を追跡しているのかはわかりません。スレッドごとの合計時間と平均時間を想定し、以下のコードでアイデアを具体化しました。テストもデバッグもされていませんが、開始方法についての良いアイデアが得られるはずです。

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がタスクのリストについてあまりにも多くを知っているように見えるという点で、少し奇妙に思われることが1つあります。仕事をし、あなたがそれらを作成するときにそれらをサービスに提出します。

于 2013-03-16T21:02:57.630 に答える