1. Time API
To track performance, we need to measure the time interval, i.e. the difference between two time points.JDK
We provide two ways to get the current time:
// Milliseconds since Unix epoch (00:00:00 UTC on 1 January 1970) () // Nanoseconds since the VM started. ()
Android
Provides aSystemClock
class, it adds some:
// (API 29) Clock that starts at Unix epoch. // Synchronized using the device's location provider. () // Milliseconds running in the current thread. () // Milliseconds since boot, including time spent in sleep. () // Nanoseconds since boot, including time spent in sleep. () // Milliseconds since boot, not counting time spent in deep sleep. ()
Which one should we choose?SystemClock
ofjavadoc
Helps answer this question:
System#currentTimeMillis
It can be set by the user or telephone network, so time may jump backwards or forwards unpredictably. Different clocks should be used for interval or elapsed time measurements.
SystemClock#uptimeMillis
Stops when the system enters deep sleep. This is the basis for most interval timings, e.g.Thread#sleep(long)
、Object#wait(long)
andSystem#nanoTime
. This clock is suitable for interval timing when the interval does not sleep across the device.
SystemClock#elapsedRealtime
andSystemClock#elapsedRealtimeNanos
Including deep sleep. This clock is the recommended basis for universal interval timing.
The performance of the application has no effect on what happens in deep sleep, so our best bet is ()
and()
2、uptimeMillis() vs nanoTime()
()
CompareuptimeMillis()
More precise, but this is only useful for microbenchmarks. When tracking performance in production, we need millisecond resolution.
Let's compare their performance impact. I've cloned itAndroid Benchmark Samples
Repository and the following tests were added:
@LargeTest @RunWith(AndroidJUnit4::class) class TimingBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun nanoTime() { { () } } @Test fun uptimeMillis() { { () } } }
Results on Pixel 3 running Android 10:
()
Median time: 208 ns
()
Median time: 116 ns
()
Almost twice as fast! While this difference shouldn't have any meaningful impact on the application, can we figure out why it's much faster?
3. UptimeMillis() implementation
()
Implemented as@CriticalNative
Native method of comments.CriticalNative
Provides faster JNI conversions for methods that do not contain objects.
public final class SystemClock { @CriticalNative native public static long uptimeMillis(); }
Native implementation in ++
middle:
int64_t uptimeMillis() { int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); return (int64_t) nanoseconds_to_milliseconds(when); }
systemTime() is defined in:
nsecs_t systemTime(int clock) { static constexpr clockid_t clocks[] = { CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID, CLOCK_BOOTTIME }; timespec t = {}; clock_gettime(clocks[clock], &t); return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec; }
4. nanoTime() implementation
()
It is also implemented with@CriticalNative
Local method of comments.
public final class System { @CriticalNative public static native long nanoTime(); }
Local implementations are in:
static jlong System_nanoTime() { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); return now.tv_sec * 1000000000LL + now.tv_nsec; }
These two implementations are actually very similar, both callclock_gettime()
。
Proof of,@CriticalNative
Just recently added to()
, which explains why it slows down!
in conclusion:
When tracking performance in production applications:
For most use cases, millisecond resolution is sufficient. To measure the time interval, use ()
or()
. The latter in the olderAndroid
It's slower on the version, but that doesn't matter here.
Here's the article aboutAndroid
VariousTime API
That’s all for the detailed article. For more related contents of various Time APIs in Android, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!