Подтвердить что ты не робот

Бенчмаркинг внутри Java-кода

В последнее время я изучаю бенчмаркинг, меня всегда интересовали протоколирование данных программы и т.д. Мне было интересно узнать, можем ли мы реализовать собственный код использования памяти и эффективно реализовать наш собственный код потребления времени внутри нашей программы. Я знаю, как проверить, сколько времени требуется для запуска кода:

public static void main(String[]args){
        long start = System.currentTimeMillis();
        // code
        System.out.println(System.currentTimeMillis() - start);
    }

Я также рассмотрел Надежный Java-бенчмаркинг, часть 1: Проблемы, этот урок очень всеобъемлющий. Отображает отрицательные эффекты System.currentTimeMillis();. Затем в учебнике предлагается использовать System.nanoTime(); (что делает его более точным?).

Я также рассмотрел Определение использования памяти в Java для использования в памяти. На веб-сайте показано, как вы можете его реализовать. Код, который был предоставлен, выглядит неэффективным, потому что человек звонит

long L = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

После этого он называет System.gc(); (4 * 4) = 16 раз. Затем повторите процесс снова. Разве это не занимает память?

Итак, можно ли встраивать эффективный бенчмаркинг в вашу Java-программу?

4b9b3361

Ответ 1

Да, можно эффективно реализовать тесты производительности в Java-коде. Важный вопрос заключается в том, что любой из этапов производительности будет добавлять свои собственные накладные расходы и сколько из них вы хотите. System.currentMill..() является достаточно хорошим эталоном производительности, и в большинстве случаев nanoTime() является излишним.

Для памяти System.gc отобразит различные результаты для разных прогонов (поскольку gc-run никогда не гарантируется.) Обычно я использую Visual VM для профилирования памяти (ее бесплатно), а затем использую TDA для анализа дампов.

Один из способов сделать это менее инвазивным - использовать аспект ориентированную программирование. Вы можете создать только один аспект, который запускается на определенной аннотации или наборе методов, и напишите совет @Around для сбора данных о производительности.

Вот небольшой фрагмент:

public class TestAspect {

    @LogPerformance
    public void thisMethodNeedsToBeMonitored(){
        // Do Something
    }
    public void thisMethodNeedsToBeMonitoredToo(){
        // Do Something
    } 
}

@interface LogPerformance{}

@Aspect
class PerformanceAspect{
    @Around("the pointcut expression to pick up all " +
            "the @PerfMonitor annotated methods")
    public void logPerformance(){
        // log performance here
        // Log it to a file
    }
}

Ответ 2

Возможно, невозможно измерить без какого-либо эффекта Гейзенберга, т.е. также будет измерен ваш скамьежный код. Однако, если вы измеряете с достаточно высокой степенью детализации, эффект будет незначительным.

Ответ 3

Любой код бенчмаркинга будет менее эффективным, чем не-бенчмаркированный код, основанный на том, чтобы иметь больше возможностей для работы. Тем не менее, Java, в частности, вызывает проблемы, о которых говорится в статье, из-за того, что сбор мусора происходит каждый раз, когда это похоже на jre. Даже в документации для System.gc говорится, что он делает "лучшее усилие".

Что касается ваших конкретных вопросов:

System.gc не должен занимать больше памяти, но для этого потребуются ресурсы процессора.

Это несколько возможно на основе того, что вы пытаетесь сравнить. Там будет какое-то вмешательство. Если вы хотите выйти за пределы своего кода, есть инструменты, такие как VisualVM, для просмотра использования памяти вне вашего приложения.

Изменить: Исправлена ​​формулировка того, что говорят System.gc.