java cpu分析准确性

标签 java profiling visualvm jvm-hotspot

我尝试确保一些(免费)java cpu 分析工具的准确性,例如sjk,视觉虚拟机。

这是一个执行 CPU 敏感任务的示例程序:

RandomStringUtils.java:

import java.util.Random;

public class RandomStringUtils {
    public String generate() {
        int leftLimit = 97; // letter 'a'
        int rightLimit = 122; // letter 'z'
        int targetStringLength = 10;
        Random random = new Random();
        StringBuilder buffer = new StringBuilder(targetStringLength);
        for (int i = 0; i < targetStringLength; i++) {
            int randomLimitedInt = leftLimit + (int)
                (random.nextFloat() * (rightLimit - leftLimit + 1));
            buffer.append((char) randomLimitedInt);
        }

        return buffer.toString();
    }
}

MainClass.java:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MainClass {

    public String crypt(String str) {
        if (str == null || str.length() == 0) {
            throw new IllegalArgumentException("String to encript cannot be null or zero length");
        }
        StringBuilder hexString = new StringBuilder();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte[] hash = md.digest();
            for (byte aHash : hash) {
                if ((0xff & aHash) < 0x10) {
                    hexString.append("0" + Integer.toHexString((0xFF & aHash)));
                } else {
                    hexString.append(Integer.toHexString(0xFF & aHash));
                }
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return hexString.toString();
    }

    public static void main(String[] args) {
        long N = 1000 * 100;
        if (args.length > 0) {
            N = Long.parseLong(args[0], 10);
        }
        MainClass main = new MainClass();
        RandomStringUtils randomStringUtils = new RandomStringUtils();
        for (long i = 0; i < N; i++) {
            main.crypt(randomStringUtils.generate());
        }
    }
}

比如我使用sjk对cpu进行采样:

java -jar sjk-plus-0.11.jar stcap -p 3113 -f main -i 5ms -t 30s -o dump.std
java -jar sjk-plus-0.11.jar flame -f dump.std -o report.html

enter image description here

这里我的问题是,为什么main()的self时间这么大?并且它只执行循环。 encrypt()generate()不是占用整个cpu吗?

visualvm 显示了类似的结果。

sjk有考虑 self 时间和整体时间吗?顺便说一句,如何在命令行报告中显示它们?

最佳答案

这是安全点偏差的一个非常引人注目的例子。

下面的 3 个火焰图是您的代码稍作修改的版本 ( see on github )。

使用 SJK 抽样 Sampling with SJK

SJK 正在使用线程转储采样方法,因此结果存在 safepoint 的偏差。偏见。

使用 Java Flight Recorder enter image description here

JFR 不受采样时安全点偏差的影响,但 JIT 编译器生成的符号映射默认仅限于安全点检查。这对重建堆栈跟踪有负面影响。

虽然结果比线程转储采样更好,但您可以看到异常情况。例如。 Integer.toHexString时间肯定被夸大了。

使用 Java Flight Recorder 和其他 JVM 选项

-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints

enter image description here

对 JVM 启动选项图片的调整变得更加准确和详细。 -XX:+DebugNonSafepoints 强制 JIT 编译器生成详细的符号映射。

通过这个示例,您可以得出结论:Java Flight Recorder 总体上更好。

Here您可以找到对此现象更详细的解释。

关于java cpu分析准确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54005401/

相关文章:

java - 椭圆不会出现在 jframe 上

Java 网络摄像头捕获和显示

c - 在 Linux 上以编程方式获取函数的总时间和忙碌时间

jmx - 以编程方式执行远程堆转储

java - 为什么 VisualVM 中的 CPU 时间不加起来?

java - 是否可以在不创建b​​ean的情况下使用Spring AOP?

java - HTTPS Volley Invalid header 问题

c - 衡量分支预测命中率的方法

visual-studio-2012 - Visual Studio 2012分析远程调试过程

java - 关于线程和 JVisualVM