Что является чистым способом выполнения кода в Java?

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

long start = System.nanoTime();

// The code you want to time

long end = System.nanoTime();
System.out.printf("That took: %d ms.%n", TimeUnit.NANOSECONDS.toMillis(end - start));

Попытка

Я придумал следующее, это выглядит намного лучше, есть несколько преимуществ и недостатков:

Преимущества:

  • Понятно, что рассчитывается из-за отступа
  • Он автоматически выведет, сколько времени прошло после завершения кода

Недостатки:

  • Это не так AutoClosable должен быть использован (уверен)
  • Это создает новый экземпляр TimeCode что не хорошо
  • Переменные, объявленные в try блок не доступен за его пределами

Это можно использовать так:

 try (TimeCode t = new TimeCode()) {
     // The stuff you want to time
 }

Код, который делает это возможным:

class TimeCode implements AutoCloseable {

    private long startTime;

    public TimeCode() {
        this.startTime = System.nanoTime();
    }

    @Override
    public void close() throws Exception {
        long endTime = System.nanoTime();
        System.out.printf("That took: %d ms%n",
                TimeUnit.NANOSECONDS.toMillis(endTime - this.startTime));
    }

}

Вопрос

Мой вопрос:

  • Мой метод на самом деле так плох, как я думаю,
  • Есть ли лучший способ для тайм-кода выполнения в Java, где вы можете четко видеть, что рассчитывается по времени, или я просто должен согласиться на что-то вроде моего первого блока кода.

4 ответа

Решение

Вы решение просто отлично.

Менее выразительный способ - обернуть ваш код в лямбду.

public void timeCode(Runnable code) {
    ...
    try {
        code.run();
    } catch ...
    }
    ...
}

timeCode(() -> { ...code to time... });

Вы, вероятно, хотели бы перехватить проверенные исключения и передать их в какое-то исключение времени выполнения или что-то еще.

Ваш метод великолепен как есть. Мы используем что-то подобное профессионально, но написано на C#.

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

Дополнительные улучшения, которые я хотел бы рассмотреть, - это создание некоторого статического состояния приложения (злоупотребление локальными потоками), чтобы вы могли вкладывать эти разделы и получать сводные разбивки.

Смотрите https://github.com/aikar/minecraft-timings для библиотеки, которая делает это для моддинга Minecraft (написано на Java).

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

И проект Guava, и Apache Commons включают классы секундомера. Используя любой из них, код будет легче читать и понимать, и они также обладают большей функциональностью.

Даже без использования оператора try-with-resource измеряемая секция может быть заключена в блок для улучшения ясности:

// Do things that shouldn't be measured

{
    Stopwatch watch = Stopwatch.createStarted();

    // Do things that should be measured

    System.out.println("Duration: " + watch.elapsed(TimeUnit.SECONDS) + " s");
}

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

@Pointcut("(execution(* com.resources.delegate.*.*(..)) "
        + "|| execution(* com.resources.implementation.*.*(..))) ")
public void resourceLayerPointCut() {
}

@Pointcut("(execution(* com.models.delegate.*.*(..)) "
        + "|| execution(* com.repo.implementation.*.*(..))) ")
public void exclusionsPointcut() {
}

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

@Around(value = "resourceLayerPointCut() && exclusionsPointcut()")
public Object aroundResourceLayerMethods(ProceedingJoinPoint code) throws Throwable {
    long startTime = System.currentTimeMillis();
    Object returnValue = null;
  try {

        //This will call your methods

        returnValue = code.proceed();
     } catch (Throwable e) {
        log(joinPoint, startTime, returnValue, Layer.ResourceLayer, true);
        throw (e);
    }

    long endTime = System.currentTimeMillis();
    System.out.printf("That took: %d ms%n", endTime - this.startTime);
    return returnValue;

}
Другие вопросы по тегам