Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java VisualVM为CPU评测提供了奇怪的结果-还有其他人遇到过这种情况吗?_Java_Visualvm_Profiling - Fatal编程技术网

Java VisualVM为CPU评测提供了奇怪的结果-还有其他人遇到过这种情况吗?

Java VisualVM为CPU评测提供了奇怪的结果-还有其他人遇到过这种情况吗?,java,visualvm,profiling,Java,Visualvm,Profiling,我已经编写了这个小(而且效率极低)类,并希望使用Java VisualVM对其进行评测 public class Test { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); br.readLine(); int n =

我已经编写了这个小(而且效率极低)类,并希望使用Java VisualVM对其进行评测

public class Test {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();
        int n = Integer.parseInt(args[0]);
        int fib = fib(n);
        System.out.println(fib);
    }

    private static int fib(int n) {
        if (n < 2) {
            return n;
        }
        return fib(n-1)+fib(n-2);
    }
}
公共类测试{
公共静态void main(字符串[]args)引发IOException{
BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
br.readLine();
int n=Integer.parseInt(args[0]);
int fib=fib(n);
系统输出打印LN(fib);
}
专用静态整数fib(整数n){
if(n<2){
返回n;
}
返回fib(n-1)+fib(n-2);
}
}
结果很奇怪。结果完全由对ConnectionHandler.run()的调用控制

(98.2%)sun.rmi.transport.tcp.tcpttransport$ConnectionHandler.run()
(1.7%)java.lang.Thread.join(长)
(0%)java.lang.String.equals(对象)
等等

大概有大约一百种方法,其中没有一种是fib(int)

我的程序实际上把所有的时间都花在这些方法上,这是不可想象的。它们似乎是连接到我的jvm并执行其任务的探查器

我做错了什么

为清晰起见进行了编辑:如果n的值超过45,则此应用程序将运行20秒。我最初评测的程序(不是斐波那契计算器)将我的cpu上的所有四个内核都钉在100%的位置,我评测的运行时间长达5分钟。这些都有相同的结果,我的应用程序中的方法并没有在热点方法列表中显示得很高

它因运行而异,但ConnectionHandler.run()始终位于顶部,通常占配置文件时间的99%

第二次编辑:我尝试过使用取样器,现在得到的结果与JProfiler产生的结果一致。这样做的缺点是,我无法获得评测附带的堆栈跟踪信息。但对于我眼前的需要,这是极好的

我在玩游戏时发现,VisualVM在分析方法调用时会计算方法调用的挂钟时间

在我的特定情况下,我的应用程序有一个主线程,它启动工作线程并立即阻止队列中的消息等待

这意味着阻塞方法似乎会占用探查器上几乎所有的时间,尽管占用我CPU的不是这个方法


我希望sun.rmi.transport.tcp.tcpttransport$ConnectionHandler.run()方法也是如此,它能很好地完成它的工作,但当它终止时,它会成为我的应用程序中运行时间最长的方法之一。我猜你给fib传递的值太小了,而且程序运行的时间不够长,无法注册。在评测(或基准点)时,要获得几乎所有内容的有意义数据,通常需要至少几秒钟的时间。

我认为这一点都不不可思议。您有一个应用程序,其中“负载”相当小(尽管这当然取决于
n
的值),您必须接受所需的额外工作(连接探查器并将所有信息转移到它)将淹没该负载

这不是我首先要分析的那种应用程序,因为很明显,大量的时间都会花在
fib
上(对于非平凡的
n
),这是一个明显的优化目标

我更倾向于将探查器用于以下更重要的应用:

  • 优化工作的方向并不明显;及
  • 在有效载荷中有大量的工作要做
如果您真的想测试该代码,您可能需要(例如)替换以下内容以提高其效果:

int fib = fib(n);
与:

for(int i=0;i<100000;i++){
int fib=fib(n);
)

不过,我要告诉你一件事要注意,我不知道任何特定JVM的内部结构,但是使用递归方法(参数的减少很慢)通常是个坏主意,这会导致堆栈空间很快耗尽

我的意思是,二进制搜索是一个很好的候选者,因为它在每个递归级别删除了一半剩余的搜索空间(因此十亿个项目的搜索空间只有30个级别)

另一方面,对数字100000000的斐波那契序列使用递归将需要大约十亿个级别,而大多数堆栈将很难包含这一级别


尾端递归优化可能会避免这个问题,但如果没有进行优化,您需要小心。

jvisualvm评测可能会在加载时将字节码编织到类中。因为您的程序只有一个类,并且在jvisualvm到达现场时它已经初始化,所以我认为它不可能仪器化的

将fib方法移动到另一个类中,然后再次尝试分析。在jvisualvm中启用cpu分析之前,可以添加jvm选项“-verbose:class”以仔细检查该类是否未加载


编辑:谢谢JB的评论。忘了我的类加载废话吧。我的直觉是fib方法与主方法的耦合太紧密了,所以它实际上是当前正在执行的字节码。

根据Ron的回答,可以通过在启动后立即停止JVM,然后激活探查器,最后启动一个之后(按enter键)继续超量。这是原油

class Foobar {
    /* First line in Class */
      static {
        try {
            System.in.read();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    /* .. */
    public static void main(..) {
        doMagic()
    }
}        

谢谢你深思熟虑的回答。我对分析递归斐波那契查找器不太感兴趣。我试图用VisualVM分析一个真正的软件,但得到了同样令人困惑的结果。你使用的是CPU采样器还是插入仪器的探查器?使用了什么设置?看起来
class Foobar {
    /* First line in Class */
      static {
        try {
            System.in.read();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    /* .. */
    public static void main(..) {
        doMagic()
    }
}