2013-02-02 132 views
4

我目前正在研究某种数据库基准测试应用程序。基本上,我试图做的是模拟使用线程一定数量的客户端,这些客户端在一段时间内对数据库重复相同的操作(例如:读取操作)。
在此期间,我希望在每个线程中测量从数据库获取答案的平均延迟。我的第一选择是依赖于ThreadMXBean的getThreadCpuTime()方法(http://docs.oracle.com/javase/7/docs/api/java/lang/management/ThreadMXBean.html),但重点是操作太快而无法测量(操作之前的getThreadCpuTime()等于getThreadCpuTime())。 。测量java短时间运行的线程执行时间

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

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实例。就像我说的,我的假设是,第一个线程完成的操作发生得太快而无法实际测量。 有没有什么办法可以实现我想要做的事情?是否有可能测量这种短时间运行线程的执行时间?

在此先感谢您的帮助:)

+0

你可以添加isThreadCpuTimeSupported()和isThreadCpuTimeEnabled()成日志?遵循http://docs.oracle.com/javase/7/docs/api/java/lang/management/ThreadMXBean.html - 默认情况下,Java虚拟机可能会禁用CPU时间测量。 – iMysak

+0

另外问题 - 你需要CpuTime或每个线程的工作时间? – iMysak

+0

我其实需要为每个线程工作的时间。但是,如果我更改getThreadUserTime()的getThreadCpuTime(),结果是相同的(即零时间完成MyThread操作) – Morro

回答

1

暴露指标为简单的解决方案,你可以使用next:

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()代替。

+0

在这种情况下,如果第一个线程被调度程序中断另一个第二线程中,第二个线程的执行时间将包含在第一个线程的时间间隔[startTime,time]中。如我错了请纠正我。 – Morro

+0

@Morro,是的,你是对的。 – iMysak

0

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

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

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

有一点要考虑是采取的CPU时间,如果它是> 0,走挂钟时间如果是== 0,

+0

谢谢。这看起来绝对不是微不足道的,我可能必须找到一个解决方法:/ – Morro