точность профилирования процессора Java - PullRequest
0 голосов
/ 02 января 2019

Я пытаюсь обеспечить точность некоторых (бесплатных) инструментов профилирования java-процессоров, например, sjk, visualvm.

Вот пример программы для выполнения задач, чувствительных к процессорам:

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 для выборки процессора:

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() такое большое?И это только выполняет цикл.Разве encrypt() и generate() не занимают весь процессор?

Visualvm показывает аналогичный результат.

Считает ли sjk свое время и все время?как их показать в отчете командной строки?

1 Ответ

0 голосов
/ 11 марта 2019

Это очень яркий пример смещения безопасной точки.

Ниже 3 графиков пламени для слегка модифицированной версии вашего кода ( см. На github ).

Использование выборки SJK Sampling with SJK

SJK использует подход выборки дампа потока, поэтому результат искажается на безопасную точку смещение.

Использование 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 универсально лучше.

Здесь вы можете найтиболее подробное объяснение этого явления.

...