我使用ThreadMXBean
来获取每种方法的CPU时间,但问题是它不是单调的(对于以后实际执行的方法,时钟值可能会减少)。在Java中访问单调增加CPU时间的最佳方法是什么?请注意,我已经检查了System.nanoTime()
,但据我所知,它还包括等待时间。
更新:以下代码显示了问题:
public class HelloThread extends Thread {
public static void main(String args[]) throws Exception {
HelloThread ht = new HelloThread();
ht.a(1);
System.out.println("Hello");
}
int a(int x) {
for (int i = 0; i < 100; i++) {
x = x * 5;
}
return x;
}
}
我使用了面向方面编程(AOP)来获取线程ID和CPU时间(我希望单调增加)。这里的输出是(方法名称,thread-id,时间,以毫秒为单位)格式:
public static void main(String[]) 1 647.971834
int HelloThread.a(int) 1 1318.913474
void java.io.PrintStream.println(String) 1 1339.034116
End 1 670.156696
AOP代码:
aspect Profiler {
pointcut mainStarting(): execution(public static void main(..));
pointcut mainEnding(): execution(public static void main(..));
pointcut methodCallBegin(): call(* * (..));
pointcut methodCallEnd(): call(* * (..));
static ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
double getTime() {
return (threadBean.getCurrentThreadCpuTime() / 1000000.0);
}
before(): mainStarting() {
System.out.println(Thread.currentThread().getId() + " " + getTime());
}
after(): mainEnding() {
System.out.println(Thread.currentThread().getId() + " " + getTime());
}
before(): methodCallBegin() {
System.out.println(Thread.currentThread().getId() + " " + getTime());
}
after(): methodCallEnd() {
System.out.println(Thread.currentThread().getId() + " " + getTime());
}
}
我在Intel(R)Xeon(R)CPU E5-2630(6核处理器)上使用OpenJDK(java 1.7.0_55)运行它。
答案 0 :(得分:2)
似乎发布的方面无法按预期工作。可能因为拦截每一个电话都太多了(我不是AOP的专家)。我稍微改了一下,只拦截System.out.println
和import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
aspect Profiler {
pointcut mainStarting(): execution(public static void main(..));
pointcut mainEnding(): execution(public static void main(..));
pointcut methodCallBegin(): (call(* *.a (..)) || call(* *.println (..)));
pointcut methodCallEnd(): (call(* *.a (..)) || call(* *.println (..)));
static ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
double getTime() {
return (threadBean.getCurrentThreadCpuTime() / 1000000.0);
}
before(): mainStarting() {
System.out.print("mainStarting: "+Thread.currentThread().getId()
+ " " + getTime()+"\n");
}
after(): mainEnding() {
System.out.print("mainEnding: "+Thread.currentThread().getId()
+ " " + getTime()+"\n");
}
before(): methodCallBegin() {
System.out.print("methodCallBegin: "+Thread.currentThread().getId()
+ " " + getTime()+"\n");
}
after(): methodCallEnd() {
System.out.print("methodCallEnd: "+Thread.currentThread().getId()
+ " " + getTime()+"\n");
}
}
来电:
mainStarting: 1 93.6006
methodCallBegin: 1 93.6006
methodCallEnd: 1 93.6006
methodCallBegin: 1 93.6006
Hello
methodCallEnd: 1 93.6006
mainEnding: 1 93.6006
现在典型的结果如下:
a
结果是预期的:这样简单的代码运行得如此之快,以至于CPU时间计数器根本不会增加(至少在Windows平台上可能具有比Linux更低的分辨率)。然而,这样的代码不能像样本输出中显示的那样花费500毫秒。它非常快。
我可以让public static void main(String args[]) throws Exception {
HelloThread ht = new HelloThread();
int b = ht.a(1);
System.out.println("Hello");
}
int a(int x) {
for (int i = 0; i < 1000000; i++) {
x = x * 5;
}
return x;
}
方法更慢:
mainStarting: 1 93.6006
methodCallBegin: 1 93.6006
methodCallEnd: 1 109.2007
methodCallBegin: 1 109.2007
Hello
methodCallEnd: 1 109.2007
mainEnding: 1 109.2007
在这种情况下,结果如下:
a
因此getCurrentThreadCpuTime()
调用正确地增加了CPU时间。没有观察到减少。一般来说for(i=number1;i<=number2;i++)
{
sum = 0; // You must make sum = 0 here
for(j=1;j<=i;j++)
{
sum=sum+j;
}
cout<<sum<<endl;
}
不应该产生显着的减少。似乎您的原始代码与发布的代码不同。