Android中各種Time API詳細(xì)
1、時(shí)間API
為了跟蹤性能,我們需要測(cè)量時(shí)間間隔,即兩個(gè)時(shí)間點(diǎn)之間的差異。 JDK
為我們提供了兩種獲取當(dāng)前時(shí)間的方法:
// Milliseconds since Unix epoch (00:00:00 UTC on 1 January 1970) System.currentTimeMillis() // Nanoseconds since the VM started. System.nanoTime()
Android
提供了一個(gè) SystemClock
類,它增加了一些:
// (API 29) Clock that starts at Unix epoch. // Synchronized using the device's location provider. SystemClock.currentGnssTimeClock() // Milliseconds running in the current thread. SystemClock.currentThreadTimeMillis() // Milliseconds since boot, including time spent in sleep. SystemClock.elapsedRealtime() // Nanoseconds since boot, including time spent in sleep. SystemClock.elapsedRealtimeNanos() // Milliseconds since boot, not counting time spent in deep sleep. SystemClock.uptimeMillis()
我們應(yīng)該選擇哪一個(gè)? SystemClock
的 javadoc
有助于回答這個(gè)問(wèn)題:
System#currentTimeMillis
可以由用戶或電話網(wǎng)絡(luò)設(shè)置,因此時(shí)間可能會(huì)不可預(yù)測(cè)地向后或向前跳躍。 間隔或經(jīng)過(guò)時(shí)間測(cè)量應(yīng)使用不同的時(shí)鐘。
SystemClock#uptimeMillis
在系統(tǒng)進(jìn)入深度睡眠時(shí)停止。 這是大多數(shù)間隔計(jì)時(shí)的基礎(chǔ),例如 Thread#sleep(long)
、Object#wait(long)
和 System#nanoTime
。 當(dāng)間隔不跨越設(shè)備休眠時(shí),該時(shí)鐘適用于間隔計(jì)時(shí)。
SystemClock#elapsedRealtime
和 SystemClock#elapsedRealtimeNanos
包括深度睡眠。 該時(shí)鐘是通用間隔計(jì)時(shí)的推薦基礎(chǔ)。
應(yīng)用程序的性能對(duì)深度睡眠中發(fā)生的事情沒(méi)有影響,所以我們最好的選擇是 SystemClock.uptimeMillis()
和 System.nanoTime()
2、uptimeMillis() vs nanoTime()
System.nanoTime()
比 uptimeMillis()
更精確,但這僅對(duì)微基準(zhǔn)測(cè)試有用。 在生產(chǎn)中跟蹤性能時(shí),我們需要毫秒級(jí)的分辨率。
讓我們比較一下它們的性能影響。 我克隆了 Android Benchmark Samples
存儲(chǔ)庫(kù)并添加了以下測(cè)試:
@LargeTest @RunWith(AndroidJUnit4::class) class TimingBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun nanoTime() { benchmarkRule.measureRepeated { System.nanoTime() } } @Test fun uptimeMillis() { benchmarkRule.measureRepeated { SystemClock.uptimeMillis() } } }
在運(yùn)行 Android 10 的 Pixel 3 上的結(jié)果:
System.nanoTime()
中值時(shí)間:208 ns
SystemClock.uptimeMillis()
中值時(shí)間:116 ns
SystemClock.uptimeMillis()
幾乎快兩倍! 雖然這種差異應(yīng)該不會(huì)對(duì)應(yīng)用程序產(chǎn)生任何有意義的影響,但我們能弄清楚為什么它要快得多嗎?
3、uptimeMillis() 實(shí)現(xiàn)
SystemClock.uptimeMillis()
實(shí)現(xiàn)為帶有@CriticalNative
注釋的本機(jī)方法。 CriticalNative
為不包含對(duì)象的方法提供更快的 JNI 轉(zhuǎn)換。
public final class SystemClock { @CriticalNative native public static long uptimeMillis(); }
原生實(shí)現(xiàn)在 SystemClock.c++
中:
int64_t uptimeMillis() { int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); return (int64_t) nanoseconds_to_milliseconds(when); }
systemTime() 在 Timers.cpp 中定義:
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() 實(shí)現(xiàn)
System.nanoTime()
也被實(shí)現(xiàn)為帶有@CriticalNative
注釋的本地方法。
public final class System { @CriticalNative public static native long nanoTime(); }
本地實(shí)現(xiàn)在 System.c 中:
static jlong System_nanoTime() { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); return now.tv_sec * 1000000000LL + now.tv_nsec; }
這兩個(gè)實(shí)現(xiàn)其實(shí)很相似,都調(diào)用clock_gettime()
。
事實(shí)證明,@CriticalNative
最近才被添加到 System.nanoTime()
,這就解釋了為什么它變慢了!
結(jié)論:
在生產(chǎn)應(yīng)用中跟蹤性能時(shí):
對(duì)于大多數(shù)用例,毫秒分辨率就足夠了。 要測(cè)量時(shí)間間隔,請(qǐng)使用 SystemClock.uptimeMillis()
或 System.nanoTime()
。 后者在較舊的 Android
版本上速度較慢,但這在這里無(wú)關(guān)緊要。
到此這篇關(guān)于Android
中各種Time API
詳細(xì)的文章就介紹到這了,更多相關(guān)Android中各種Time API內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Flutter源碼分析之自定義控件(RenderBox)指南
寫(xiě)了兩天的flutter,發(fā)現(xiàn)控件樣式很多,flutter資源很少,本文在于實(shí)用性,可以減少頁(yè)面代碼,下面這篇文章主要介紹了Flutter源碼分析之自定義控件(RenderBox)的相關(guān)資料,需要的朋友可以參考下2021-08-08全面解析Android中對(duì)EditText輸入實(shí)現(xiàn)監(jiān)聽(tīng)的方法
這篇文章主要介紹了Android中對(duì)EditText輸入實(shí)現(xiàn)監(jiān)聽(tīng)的方法,包括一個(gè)仿iOS的帶清除功能的ClearEditText輸入框控件的詳細(xì)使用介紹,需要的朋友可以參考下2016-04-04Android的WebView與H5前端JS代碼交互的實(shí)例代碼
本篇文章主要介紹了Android的WebView與H5前端JS代碼交互的實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-07-07Android實(shí)現(xiàn)將應(yīng)用崩潰信息發(fā)送給開(kāi)發(fā)者并重啟應(yīng)用的方法
這篇文章主要介紹了Android實(shí)現(xiàn)將應(yīng)用崩潰信息發(fā)送給開(kāi)發(fā)者并重啟應(yīng)用的方法,涉及Android錯(cuò)誤處理與應(yīng)用操作的相關(guān)技巧,需要的朋友可以參考下2016-03-03Android利用RecyclerView實(shí)現(xiàn)列表倒計(jì)時(shí)效果
這篇文章主要為大家詳細(xì)介紹了Android利用RecyclerView實(shí)現(xiàn)列表倒計(jì)時(shí)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09基于Android中獲取資源的id和url方法總結(jié)
下面小編就為大家分享一篇基于Android中獲取資源的id和url方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02Android Framework Application Framework層簡(jiǎn)單介紹
這篇文章主要介紹了 Android Framework Application Framework層簡(jiǎn)單介紹的相關(guān)資料,需要的朋友可以參考下2016-11-11Android提高之BLE開(kāi)發(fā)Android手機(jī)搜索iBeacon基站
這篇文章主要介紹了BLE開(kāi)發(fā)Android手機(jī)搜索iBeacon基站,需要的朋友可以參考下2014-08-08