深入V8引擎-Time核心方法之win篇(1)
上一篇的源码看得十分无趣,官方文档跟黑心棉一样渣。
这一篇讲讲windows操作系统上的时间戳实现,由于类的声明,方法解释上一篇都贴过了,所以这次直接上对应版本的代码。
windows与mac很不一样,实现了一个新的Clock类来管理时间,如下。
// We implement time using the high-resolution timers so that we can get
// timeouts which are smaller than 10-15ms. To avoid any drift, we
// periodically resync the internal clock to the system clock.
class Clock final {
public:
Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {} Time Now() { /* */ } Time NowFromSystemTime() { /* */ } private:
static TimeTicks GetSystemTicks() { /* */ } static Time GetSystemTime() { /* */ } TimeTicks initial_ticks_;
Time initial_time_;
Mutex mutex_;
};
从注释和方法名可以看出,windows完全用这个新类代替了老的Time、TimeTicks,因为这个方法拥有更好的性能,这个类同时会周期性的与系统时间同步数据。
下面正式开始。
先从Now方法看起,看windows系统是如何获取本地的时间戳。
DEFINE_LAZY_LEAKY_OBJECT_GETTER(Clock, GetClock) #define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName, ...) \
T* FunctionName() { \
static ::v8::base::LeakyObject<T> object{__VA_ARGS__}; \
return object.get(); \
} Time Time::Now() { return GetClock()->Now(); }
这个方法的定义也不一般,直接用了一个特殊宏,宏就不展开了,简单说就是懒加载,调用的时候会分配空间生成一个Clock类,初始化完后第二次调用就直接返回了,当成一个单例来理解。
直接看宏的返回类型,刚好是上面的Clock,该类只有一个无参构造函数,初始化两个时间戳属性。
先看后那个,也就是系统时间的时间戳。
static Time GetSystemTime() {
FILETIME ft;
::GetSystemTimeAsFileTime(&ft);
return Time::FromFiletime(ft);
}
这里的FILETIME和GetSystemTimeAsFileTime都是windowsAPI,可以获取当前系统的日期和时间,但是返回值很奇怪。
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
这是结构体的声明与解释,High、Low分别代表时间的高位与地位,而那个方法就是配合这个使用的。
可以从上面看到,这个API返回的时间竟然是从1601年1月1日开始算的,不知道那一年发生了什么。
下面写一个测试代码。
int main()
{
FILETIME ft;
LARGE_INTEGER t;
::GetSystemTimeAsFileTime(&ft);
t.LowPart = ft.dwLowDateTime;
t.HighPart = ft.dwHighDateTime;
cout << t.QuadPart << endl;
}
得到的输出为132034487665022709,由于单位是100纳秒,所以这个数字乘以100的,然后换算一下。

由于基准是1601年,而Date是从1970年开始算,所以年份上差了369年,刚好是2019,很合理。
来看看V8的处理。
// Time between windows epoch and standard epoch.
static const int64_t kTimeToEpochInMicroseconds = int64_t{}; Time Time::FromFiletime(FILETIME ft) {
// 特殊情况处理
if (ft.dwLowDateTime == && ft.dwHighDateTime == ) {
return Time();
}
if (ft.dwLowDateTime == std::numeric_limits<DWORD>::max() &&
ft.dwHighDateTime == std::numeric_limits<DWORD>::max()) {
return Max();
}
// 换算
int64_t us = (static_cast<uint64_t>(ft.dwLowDateTime) +
(static_cast<uint64_t>(ft.dwHighDateTime) << )) / ;
return Time(us - kTimeToEpochInMicroseconds);
}
前面的特殊情况看看就行了,主要是换算这一步,就是简单的将高低位的数值拼到了一起,除以10之后,单位从100纳秒变成了微秒。
最后的计算,也是为了平衡标准的时间戳和windows时间戳两者的差异,如下。

为什么不是1970 - 1601 = 369年整呢?因为中间有闰年,很合理。
最后得到微秒单位的标准时间戳,将该数值赋到类的属性上。
回到最初的Now方法,初始化完后,会调用Clock自身的Now方法获取最终的时间戳,如下。
Time Now() {
// 一个误差临界值
const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes();
// 我目前不想解析所有关于锁的东西
MutexGuard lock_guard(&mutex_);
// 再次获取当前的硬件时间戳与本地时间戳
TimeTicks ticks = GetSystemTicks();
Time time = GetSystemTime();
// 这里进行误差修正
TimeDelta elapsed = ticks - initial_ticks_;
// 1.当前时间小于初始化时间 可参考上一篇中类方法的注释(the system might adjust its clock...)
// 2.硬件时间戳的时间差超过临界值 这种情况基本可以认定初始化的时间完全不可信了
if (time < initial_time_ || elapsed > kMaxElapsedTime) {
initial_ticks_ = ticks;
initial_time_ = time;
return time;
}
return initial_time_ + elapsed;
}
虽然在构造函数中获取了时间戳,但是V8考虑到由于函数调用、系统修正等原因导致的误差(比如第一次初始化),再次进行了修正,具体操作和原因可以直接看注释,最后返回的时间戳是计算获得的理论本地时间戳加上硬件时间戳差值。
至于NewFromSystemTime就比较简单了,在mac中这两个方法是一个,在windows里如下。
Time NowFromSystemTime() {
MutexGuard lock_guard(&mutex_);
// 更新两个时间戳
initial_ticks_ = GetSystemTicks();
initial_time_ = GetSystemTime();
// 直接返回最新获得的时间戳
return initial_time_;
}
不计算任何东西,直接返回系统API的时间戳,可以配合注释来理解这两个方法。
尴尬了,没想到V8在Time阶段把两个时间戳全用上了。稍微看了一下TimeTicks的实现,发现还有点意思,所以这一篇先这样了,太长了写的累。
深入V8引擎-Time核心方法之win篇(1)的更多相关文章
- 深入V8引擎-Time核心方法之win篇(2)
这一篇讲windows系统下TimeTicks的实现. 对于tick,V8写了相当长的一段discussion来讨论windows系统上计数的三种实现方法以及各自的优劣,注释在time.cc的572行 ...
- 深入V8引擎-Time核心方法之mac篇
由于底层逻辑实现不同操作系统区别很大,所以干脆分篇来说. 主要讲一下Time.TimeTicks两个类里面对于时间戳的实现,其余的运算符重载.边缘工具方法就不看了,先是Time. Time 类本身的说 ...
- 浅谈Chrome V8引擎中的垃圾回收机制
垃圾回收器 JavaScript的垃圾回收器 JavaScript使用垃圾回收机制来自动管理内存.垃圾回收是一把双刃剑,其好处是可以大幅简化程序的内存管理代码,降低程序员的负担,减少因 长时间运转而带 ...
- 浅谈V8引擎中的垃圾回收机制
最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...
- 深入出不来nodejs源码-V8引擎初探
原本打算是把node源码看得差不多了再去深入V8的,但是这两者基本上没办法分开讲. 与express是基于node的封装不同,node是基于V8的一个应用,源码内容已经渗透到V8层面,因此这章简述一下 ...
- Chrome V8引擎系列随笔 (1):Math.Random()函数概览
先让大家来看一幅图,这幅图是V8引擎4.7版本和4.9版本Math.Random()函数的值的分布图,我可以这么理解 .从下图中,也许你会认为这是个二维码?其实这幅图告诉我们一个道理,第二张图的点的分 ...
- (译)V8引擎介绍
V8是什么? V8是谷歌在德国研发中心开发的一个JavaScript引擎.开源并且用C++实现.可以用于运行于客户端和服务端的Javascript程序. V8设计的初衷是为了提高浏览器上JavaScr ...
- V8引擎嵌入指南
如果已读过V8编程入门那你已经熟悉了如句柄(handle).作用域(scope)和上下文(context)之类的关键概念,以及如何将V8引擎作为一个独立的虚拟机来使用.本文将进一步讨论这些概念,并介绍 ...
- EF5+MVC4系列(9) Razor视图引擎的核心原理;@符号的使用;输出html的转义
一:Razor视图引擎的核心原理 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项 ,他是一个视图引擎 他的核心原理,就是当读取到 @符号的时候,就认为这是开始 ...
随机推荐
- secureCRT中vim行号下划线问题
在vim中发现开启显示行号(set number)或语法高亮(syntax on)时,发现文档中很多地方都有下划线,对视觉产生极大干扰.开始还以为是vim的某个配置造成的,后来发现真正的元凶是secu ...
- 笔记-python-内存管理
笔记-python-内存管理 1. 内存使用 1.1. 对象的内存使用 a = 1 1是一个对象,a是引用,指向1. >>> id(a) 1951821280 这个数 ...
- centos6.4编译hadoop2.4源码
4.1.环境: 1)Linux 64 位操作系统,CentOS 6.4 版本,VMWare 搭建的虚拟机 2)虚拟机可以联网 4.2.官方编译说明: 解压命令:tar -zxvf hadoop-2.4 ...
- BZOJ 4971: [Lydsy1708月赛]记忆中的背包
神仙构造 分成x个1和一堆>=w-x的大物品 (x<=20 w>=50) 则拼成w的方案中有且仅有一个大物品 若最终序列中有x个1,有一个大物品为w-k,可以提供C(x,k)种方案 ...
- python中pip 出错
错误:error in launcher: Unable to create process using '" python多个版本时出现, 解决方法-- 将pip重新安装 python3 ...
- 【Scramble String】cpp
题目: Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty subs ...
- 【Jump Game】cpp
题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...
- IOS开发学习笔记027-UITableView 使用模型对象
1.模型对象 2.单组数据的显示 1.模型对象 继续优化上一个程序 上一次用到字典,但是坏处多多.这里将这些数据封装到类中. 这就是MVC中得模型,模型就是数据的显示结构 新建一个类,添加几个属性和一 ...
- 【LoadRunner】loadrunner常见问题汇总
LoadRunner常见问题1.LR 脚本为空的解决方法: 1.去掉ie设置中的第三方支持取消掉 2.在系统属性-高级-性能-数据执行保护中,添加loadrunner安装目录中的vugen.exe文件 ...
- 来自知乎的pthread_cond_wait为什么总是带着mutex
来自https://www.zhihu.com/question/24116967?q=linux%20%E5%A4%9A%E7%BA%BF%E7%A8%8B%20%E8%99%9A%E5%81 ...