- Как замерить время выполнения
- Замер времени с помощью currentTimeMills()
- Замер времени с помощью nanoTime()
- Замер времени с помощью Instant и Duration
- Замер времени выполнения с помощью StopWatch
- Исходный код
- Заключение
- How to calculate the running time of my program? [duplicate]
- 6 Answers 6
- How do I measure time elapsed in Java? [duplicate]
- 15 Answers 15
- How can I count the time it takes a function to complete in Java?
Как замерить время выполнения
Зачастую требуется узнать, сколько времени выполняется тот или иной код. Иногда требуется замерить время выполнения метода или какой-то задачи. В данной статье мы расскажем вам принципы замера времени в Java и покажем лучшие практики для конкретных задач.
Замер времени с помощью currentTimeMills()
Это довольно простой способ измерить время. Метод System.currentTimeMillis() вернёт вам текущее время в миллисекундах. Его потребуется вызвать до выполнения нужной задачи и после, а затем вычислить разницу. В итоге мы узнаем время выполнения в миллисекундах:
long start = System.currentTimeMillis(); // выполнение какой-то логики Thread.sleep(1000); long finish = System.currentTimeMillis(); long elapsed = finish - start; System.out.println("Прошло времени, мс: " + elapsed);
При работе с данным методом следует учитывать его специфику: System.currentTimeMillis() показывает текущее время, основываясь на системных часах и может выдавать некорректный результат.
Замер времени с помощью nanoTime()
Ещё один метод для получения текущего времени это System.nanoTime(). Как следует из названия, этот метод возвращает время с точностью до нансекунд. Также работа этого метода не зависит от системных часов.
Он используется аналогично:
long start = System.nanoTime(); // выполнение какой-то логики Thread.sleep(1000); long finish = System.nanoTime(); long elapsed = finish - start; System.out.println("Прошло времени, нс: " + elapsed);
Для получения значения в миллисекундах результат можно разделить на 1000:
System.out.println("Прошло времени, мс: " + elapsed / 1000000);
Важно: Хотя метод nanoTime() может возвращать время в наносекундах, он не гарантирует, что значения между его вызовами будут обновляться с точностью до наносекунд.
Но всё же это более приемлемый вариант, чем System.currentTimeMillis().
Замер времени с помощью Instant и Duration
В Java 8 добавили новый java.time API. В частности, ля измерения времени подойдут два новых класса – Instant и Duration. Оба эти класса иммутабельны.
Instant обозначает момент времени с начала эпохи Unix (1970-01-01T00:00:00Z). Для создания момента мы используем метод Instant.now(). После того, как мы создали два момент, вычислим разницу в миллисекундах:
Instant start = Instant.now(); // выполнение какой-то логики Thread.sleep(1000); Instant finish = Instant.now(); long elapsed = Duration.between(start, finish).toMillis(); System.out.println("Прошло времени, мс: " + elapsed);
Рекомендуется использовать именно этот подход в Java 8 и выше.
Замер времени выполнения с помощью StopWatch
StopWatch – это класс из библиотеки Apache Commons Lang. Он работает как секундомер. Для его использования сначала требуется подключить библиотеку к проекту:
org.apache.commons commons-lang3 3.9
Теперь создадим экземпляр StopWatch. Затем начнём отсчёт с помощью метода start() и окончим отсчёт с помощью метода stop():
public static void stopWatch() throws InterruptedException < StopWatch stopWatch = new StopWatch(); stopWatch.start(); // выполнение какой-то логики Thread.sleep(1000); stopWatch.stop(); System.out.println("Прошло времени, мс: " + stopWatch.getTime()); >
StopWatch удобно использовать тогда, когда в проекте уже подключена данная библиотека.
Исходный код
package ru.javalessons.time; import org.apache.commons.lang3.time.StopWatch; import java.time.Duration; import java.time.Instant; public class MeasureElapsedTime < public static void main(String[] args) throws InterruptedException < currentTimeMillis(); nanoTime(); instant(); stopWatch(); >public static void currentTimeMillis() throws InterruptedException < long start = System.currentTimeMillis(); // выполнение какой-то логики Thread.sleep(1000); long finish = System.currentTimeMillis(); long elapsed = finish - start; System.out.println("Прошло времени, мс: " + elapsed); >public static void nanoTime() throws InterruptedException < long start = System.nanoTime(); // выполнение какой-то логики Thread.sleep(1000); long finish = System.nanoTime(); long elapsed = finish - start; System.out.println("Прошло времени, нс: " + elapsed); >public static void instant() throws InterruptedException < Instant start = Instant.now(); // выполнение какой-то логики Thread.sleep(1000); Instant finish = Instant.now(); long elapsed = Duration.between(start, finish).toMillis(); System.out.println("Прошло времени, мс: " + elapsed); >public static void stopWatch() throws InterruptedException < StopWatch stopWatch = new StopWatch(); stopWatch.start(); // выполнение какой-то логики Thread.sleep(1000); stopWatch.stop(); System.out.println("Прошло времени, мс: " + stopWatch.getTime()); >>
Заключение
В данной статье мы разобрали простые методы замера времени выполнения в Java. Для простых замеров можно использовать все вышеперечисленные методы, кроме currentTimeMillis (из-за того, что он зависит от системных часов).
How to calculate the running time of my program? [duplicate]
I wrote a program and now I want to calculate the total running time of my program from start to end. How can I do this?
6 Answers 6
Use System.nanoTime to get the current time.
long startTime = System.nanoTime(); . your program. long endTime = System.nanoTime(); long totalTime = endTime - startTime; System.out.println(totalTime);
The above code prints the running time of the program in nanoseconds.
At the beginning of your main method, add this line of code :
final long startTime = System.nanoTime();
And then, at the last line of your main method, you can add :
final long duration = System.nanoTime() - startTime;
duration now contains the time in nanoseconds that your program ran. You can for example print this value like this:
If you want to show duration time in seconds, you must divide the value by 1’000’000’000. Or if you want a Date object: Date myTime = new Date(duration / 1000); You can then access the various methods of Date to print number of minutes, hours, etc.
Use System.currentTimeMillis() or System.nanoTime() if you want even more precise reading. Usually, milliseconds is precise enough if you need to output the value to the user. Moreover, System.nanoTime() may return negative values, thus it may be possible that, if you’re using that method, the return value is not correct.
A general and wide use would be to use milliseconds :
long start = System.currentTimeMillis(); . long end = System.currentTimeMillis(); NumberFormat formatter = new DecimalFormat("#0.00000"); System.out.print("Execution time is " + formatter.format((end - start) / 1000d) + " seconds");
Note that nanoseconds are usually used to calculate very short and precise program executions, such as unit testing and benchmarking. Thus, for overall program execution, milliseconds are preferable.
How do I measure time elapsed in Java? [duplicate]
Also it is important that for example if the startTime it’s 23:00 and endTime 1:00 to get a duration of 2:00. Which types to use in order to accomplish this in Java?
The linked Question is not a duplicate. That question’s title is misleading. That question’s content is about accessing the current time from the computer clock. The answers involve ` System.currentTimeMillis()` and System.nanoTime() . This question here is focused on calculating elapsed time between two moments without regard to fetching the current time.
15 Answers 15
Unfortunately, none of the ten answers posted so far are quite right.
If you are measuring elapsed time, and you want it to be correct, you must use System.nanoTime() . You cannot use System.currentTimeMillis() , unless you don’t mind your result being wrong.
The purpose of nanoTime is to measure elapsed time, and the purpose of currentTimeMillis is to measure wall-clock time. You can’t use the one for the other purpose. The reason is that no computer’s clock is perfect; it always drifts and occasionally needs to be corrected. This correction might either happen manually, or in the case of most machines, there’s a process that runs and continually issues small corrections to the system clock («wall clock»). These tend to happen often. Another such correction happens whenever there is a leap second.
Since nanoTime ‘s purpose is to measure elapsed time, it is unaffected by any of these small corrections. It is what you want to use. Any timings currently underway with currentTimeMillis will be off — possibly even negative.
You may say, «this doesn’t sound like it would ever really matter that much,» to which I say, maybe not, but overall, isn’t correct code just better than incorrect code? Besides, nanoTime is shorter to type anyway.
Previously posted disclaimers about nanoTime usually having only microsecond precision are valid. Also it can take more than a whole microsecond to invoke, depending on circumstances (as can the other one), so don’t expect to time very very small intervals correctly.
How can I count the time it takes a function to complete in Java?
Note that the clock that nanoTime is polling is probably NOT accurate to the nanoSecond. If you’re lucky, the accuracy will be the clock speed of your CPU, otherwise it will be some multiple of that.
If you need to time your function in nanoseconds, perhaps it’s already fast enough? I just got annoyed by dividing everything by 1 billion to see how many seconds it was.
I make this and the precision was more exactly than using a timer (starting the timer just before the methodToBeTimed() and stop just after the methodToBeTimed)
Here is how can compute the elapsed time.
// Get current time long start = System.currentTimeMillis(); // Do something . // Get elapsed time in milliseconds long elapsedTimeMillis = System.currentTimeMillis()-start; // Get elapsed time in seconds float elapsedTimeSec = elapsedTimeMillis/1000F; // Get elapsed time in minutes float elapsedTimeMin = elapsedTimeMillis/(60*1000F); // Get elapsed time in hours float elapsedTimeHour = elapsedTimeMillis/(60*60*1000F); // Get elapsed time in days float elapsedTimeDay = elapsedTimeMillis/(24*60*60*1000F);
If you are using Guava, consider using the Stopwatch , e.g.:
final Stopwatch sw = Stopwatch.createStarted(); methodToBeTimed(); final long elapsedMillis = sw.elapsed(TimeUnit.MILLISECONDS);
The profiler is the right answer if you have more than one function.
Another problem that I see with all the suggestions given so far is that they work fine for a single function, but your code will be littered with timing stuff that you can’t turn off.
If you know how to do aspect oriented programming, it’s a good way to keep the timing code in one place and apply it declaratively. If you use something like Log4J to output the values, you’ll have the option of turning it off or on. It’s a poor man’s profiler.
Have a look at AspectJ or Spring’s AOP.
I agree that a profiler is overkill if you only want to time one function; however, even if you start out only wanting to time one function you generally end up timing more than that.
All of the code snippets above measure the approximate time elapsed from the time the method was invoked to the time the method returns/throws an exception. Such techniques do not address thread scheduling, pauses due the GC, etc.
Yes, some profilers will do a reasonable job.
If you are using Java 1.6 onwards, you can use the JMX based VM management and monitoring support. For example, you may find ThreadMXBean.getCurrentThreadCpuTime() of value. Calculating the difference of this value before and after the method invoke will give you:
«. the total CPU time for the current thread in nanoseconds. The returned value is of nanoseconds precision but not necessarily nanoseconds accuracy. If the implementation distinguishes between user mode time and system mode time, the returned CPU time is the amount of time that the current thread has executed in user mode or system mode.»
If your method spawns off worker threads, then your computation will need to get far more elaborate 😉
In general, I recommend nosing around the java.lang.mangement package.