深入V8引擎

2019-08-07| 发布者: admin| 查看: |

contains a 64-bit value representing the number of 100-nanosecond intervals since january 1, 1601 .

这是结构体的声明与解释,high、low分别代表时间的高位与地位,而那个方法就是配合这个使用的。

可以从上面看到,这个api返回的时间竟然是从1601年1月1日开始算的,不知道那一年发生了什么。

下面写一个测试代码。

int main
 filetime ft;
 large_integer t;
 ::getsystemtimeasfiletime;
 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{11644473600000000};
time time::fromfiletime {
 // 特殊情况处理
 if  {
 return time;
 if  
 ft.dwhighdatetime == std::numeric_limits dword ::max) {
 return max;
 // 换算
 int64_t us =  +
  32)) / 10;
 return time;
}

前面的特殊情况看看就行了,主要是换算这一步,就是简单的将高低位的数值拼到了一起,除以10之后,单位从100纳秒变成了微秒。

最后的计算,也是为了平衡标准的时间戳和windows时间戳两者的差异,如下。

为什么不是1970 - 1601 = 369年整呢?因为中间有闰年,很合理。

最后得到微秒单位的标准时间戳,将该数值赋到类的属性上。

 

回到最初的now方法,初始化完后,会调用clock自身的now方法获取最终的时间戳,如下。

time now {
 // 一个误差临界值
 const timedelta kmaxelapsedtime = timedelta::fromminutes;
 // 我目前不想解析所有关于锁的东西
 mutexguard lock_guard;
 // 再次获取当前的硬件时间戳与本地时间戳
 timeticks ticks = getsystemticks;
 time time = getsystemtime;
 // 这里进行误差修正
 timedelta elapsed = ticks - initial_ticks_;
 // 1.当前时间小于初始化时间 可参考上一篇中类方法的注释
 // 2.硬件时间戳的时间差超过临界值 这种情况基本可以认定初始化的时间完全不可信了
 if  {
 initial_ticks_ = ticks;
 initial_time_ = time;
 return time;
 return initial_time_ + elapsed;
}

虽然在构造函数中获取了时间戳,但是v8考虑到由于函数调用、系统修正等原因导致的误差,再次进行了修正,具体操作和原因可以直接看注释,最后返回的时间戳是计算获得的理论本地时间戳加上硬件时间戳差值。

至于newfromsystemtime就比较简单了,在mac中这两个方法是一个,在windows里如下。

time nowfromsystemtime {
 mutexguard lock_guard;
 // 更新两个时间戳
 initial_ticks_ = getsystemticks;
 initial_time_ = getsystemtime;
 // 直接返回最新获得的时间戳
 return initial_time_;
}

不计算任何东西,直接返回系统api的时间戳,可以配合注释来理解这两个方法。

 

尴尬了,没想到v8在time阶段把两个时间戳全用上了。稍微看了一下timeticks的实现,发现还有点意思,所以这一篇先这样了,太长了写的累。