测量java短时间运行的线程执行时间

时间:2013-02-02 18:12:08

标签: java multithreading precision

我目前正在开发某种数据库基准测试应用程序。基本上,我要做的是模拟使用一定数量的客户端线程,这些客户端在一段时间内对数据库重复相同的操作(例如:读取操作)。 在此期间,我希望在每个线程中测量从数据库中获得答案的平均延迟。

我的第一选择是依赖ThreadMXBean的getThreadCpuTime()方法(http://docs.oracle.com/javase/7/docs/api/java/lang/management/ThreadMXBean.html),但关键是操作执行得太快而无法测量(getThreadCpuTime()在操作等于getThreadCpuTime()之后操作)。

我做了一个小实验来理解和说明问题:

public class ExampleClass {
class LongRunningThread extends Thread {
    private int n;
    public LongRunningThread(int n) {
        this.n = n;
    }
    public void run() {
        ArrayList l = new ArrayList();
        for (int i = 0; i < n; i++) {
            l.add(new Object());
        }
        long time = ManagementFactory.getThreadMXBean().getThreadCpuTime(this.getId());
        System.out.println("Long running thread " + this.getId() + " execution time: " + time);
    }
}

class MyThread extends Thread {
    int n;
    public MyThread(int n) {
        this.n = n;
    }
    public void run() {
        ArrayList l = new ArrayList();
        for (int i = 0; i < n; i++) {
            l.add(new Object());
        }
        long time = ManagementFactory.getThreadMXBean().getThreadCpuTime(this.getId());
        System.out.println("My thread " + this.getId() + " execution time: " + time);
    }
}

public static void main(String [] args) {
        System.out.println("Cpu time supported? " + ManagementFactory.getThreadMXBean().isThreadCpuTimeSupported());
    System.out.println("Cpu time enabled? " + ManagementFactory.getThreadMXBean().isThreadCpuTimeEnabled());
    for (int i = 1; i < 10; ++i) {
        new LongRunningThread(i*1000000).start();
    }

    for (int i = 1; i < 10; ++i) {
        new MyThread(i*100).start();
    }
}


Output:
Cpu time supported? true
Cpu time enabled? true
My thread 18 execution time: 0
My thread 26 execution time: 0
My thread 20 execution time: 0
My thread 22 execution time: 0
My thread 24 execution time: 0
My thread 21 execution time: 0
My thread 25 execution time: 0
My thread 19 execution time: 0
My thread 23 execution time: 0
Long running thread 9 execution time: 15600100
Long running thread 10 execution time: 15600100
Long running thread 11 execution time: 46800300
Long running thread 12 execution time: 31200200
Long running thread 14 execution time: 78000500
Long running thread 13 execution time: 78000500
Long running thread 17 execution time: 124800800
Long running thread 15 execution time: 140400900
Long running thread 16 execution time: 109200700

我无法获得所有MyThread个实例的执行时间,但LongRunningThread个实例没有问题。就像我说的,我的假设是第一个线程完成的操作发生得太快而无法实际测量。 有没有办法实现我想做的事情?是否可以测量这种短时间运行线程的执行时间?

先谢谢你的帮助:)。

3 个答案:

答案 0 :(得分:2)

您是否考虑过此框架http://metrics.codahale.com/。它非常好,内置支持通过JMX公开指标

答案 1 :(得分:1)

您可以使用下一个更简单的解决方案:

class MyThread extends Thread {
    int n;
    public MyThread(int n) {
        this.n = n;
    }
    public void run() {
        long startTime = System.nanoTime();
        ArrayList l = new ArrayList(n);
        for (int i = 0; i < n; i++) {
            l.add(new Object());
        }
        long time = System.nanoTime() - startTime;
        System.out.println("My thread " + this.getId() + " execution time: " + time + " ns");
    }
}

如果您不需要纳秒精度,则可以使用System.currentTimeMillis()代替。

答案 2 :(得分:0)

  

是否可以测量这种短时间运行线程的执行时间?

如果不使用纳秒级时钟测量挂钟时间,答案可能是否定的。对于小循环,测量的CPU时间可能小于方法的精度。 javadocs for ThreadMXBean.getThreadCpuTime(...)说:

  

以毫微秒为单位返回指定ID的线程的总CPU时间。   返回值的精度为纳秒,但是   不一定是纳秒精度。

要考虑的一件事是如果它是&gt;则占用CPU时间。如果是== 0,则采用挂钟时间。