積跬步,行千里,先從最簡單的開始寫。 這一篇介紹V8中的時間模塊,與libuv粗糙的update_loop_time方法不同,V8有一套獨立完整的類負責管理時間。 該類位於src/base/platform/time.h,是一個輔助模塊,首先來看一下繼承樹。 整個模塊的繼承關係比較簡單,一般常用的就 ...
積跬步,行千里,先從最簡單的開始寫。
這一篇介紹V8中的時間模塊,與libuv粗糙的update_loop_time方法不同,V8有一套獨立完整的類負責管理時間。
該類位於src/base/platform/time.h,是一個輔助模塊,首先來看一下繼承樹。
整個模塊的繼承關係比較簡單,一般常用的就是Time、TimeTicks類,這裡挨個進行介紹吧。
TimeConstants
這個類很直接,只是定義一些常量,比如一星期有7天,一天有24小時,一小時有60分鐘等等……
class TimeConstants { public: static constexpr int64_t kHoursPerDay = 24; static constexpr int64_t kMillisecondsPerSecond = 1000; static constexpr int64_t kMillisecondsPerDay = kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; // ... };
TimeDelta
這個類提供把各種單位的時間轉換為microseconds的方法。
class V8_BASE_EXPORT TimeDelta final { public: constexpr TimeDelta() : delta_(0) {} // Converts units of time to TimeDeltas. static constexpr TimeDelta FromDays(int days) { return TimeDelta(days * TimeConstants::kMicrosecondsPerDay); } // ... }
這裡的常數定義來源於上面的TimeConstants類。
TimeBase
這個類沒啥好說的,比較特殊的地方就是這是個模版類,提供對給定類型的時間序列化功能。
template <class TimeClass> class TimeBase : public TimeConstants { public: // ... int64_t ToInternalValue() const { return us_; } // ... static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); } protected: explicit constexpr TimeBase(int64_t us) : us_(us) {} // Time value in a microsecond timebase. int64_t us_; };
Time
Time類負責管理JavaScript中Date.now生成的時間戳,用的比較多所以這裡就不解釋了。
// ----------------------------------------------------------------------------- // Time // // This class represents an absolute point in time, internally represented as // microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970. class V8_BASE_EXPORT Time final : public time_internal::TimeBase<Time> { // ... };
關於類的介紹,在註釋裡面都寫的很明白了,需要註意的是在不同的操作系統,這些方法的表現天差地別,甚至有些方法僅在指定的操作系統才能生效。
TimeTicks
// ----------------------------------------------------------------------------- // TimeTicks // // This class represents an abstract time that is most of the time incrementing // for use in measuring time durations. It is internally represented in // microseconds. It can not be converted to a human-readable time, but is // guaranteed not to decrease (if the user changes the computer clock, // Time::Now() may actually decrease or jump). But note that TimeTicks may // "stand still", for example if the computer suspended. class V8_BASE_EXPORT TimeTicks final : public time_internal::TimeBase<TimeTicks> { // ... };
註釋相當的精細。
TimeTicks這個類則負責另外一種時間戳,在淺析libuv源碼-獲取精確時間中有進行過介紹。比如在windows中,有兩種計數API,分別返回系統"心跳"一次所花時間與"心跳"次數,由於頻繁總是固定不變,所以可以根據每次返回的次數來進行計時。
這類事件戳比起上的Time優勢在於可以保證數值一直在增加,並且不會受外界因素影響(機器掛了另算)。所以無論是libuv設置輪詢開始時間或處理定時器任務,還是V8在對JS代碼進行編譯計時,都是用的這個。
最後的ThreadTicks就暫時不看了,等到時候用上了再做解釋。
這一篇先簡單介紹一下,後面再深入講一講在不同操作系統下的,兩類時間戳的具體實現。