Сравнительный анализ внутри Java-кода - PullRequest
17 голосов
/ 08 декабря 2011

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

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-программе?

Ответы [ 3 ]

11 голосов
/ 27 декабря 2011

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

Для памяти System.gc покажет вам различные результаты для разных прогонов (поскольку прогон gc никогда не гарантирован.) Обычно я использую 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
    }
}
3 голосов
/ 08 декабря 2011

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

2 голосов
/ 08 декабря 2011

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

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

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

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

Редактировать: Исправлено формулировку, содержащуюся в документации System.gc.

...