在Java

时间:2015-09-03 04:50:05

标签: java time

我使用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)运行它。

1 个答案:

答案 0 :(得分:2)

似乎发布的方面无法按预期工作。可能因为拦截每一个电话都太多了(我不是AOP的专家)。我稍微改了一下,只拦截System.out.printlnimport 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; } 不应该产生显着的减少。似乎您的原始代码与发布的代码不同。