我目前正在开发某种数据库基准测试应用程序。基本上,我要做的是模拟使用一定数量的客户端线程,这些客户端在一段时间内对数据库重复相同的操作(例如:读取操作)。 在此期间,我希望在每个线程中测量从数据库中获得答案的平均延迟。
我的第一选择是依赖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
个实例没有问题。就像我说的,我的假设是第一个线程完成的操作发生得太快而无法实际测量。
有没有办法实现我想做的事情?是否可以测量这种短时间运行线程的执行时间?
先谢谢你的帮助:)。
答案 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,则采用挂钟时间。