由于底层逻辑实现不同操作系统区别很大,所以干脆分篇来说。

  主要讲一下Time、TimeTicks两个类里面对于时间戳的实现,其余的运算符重载、边缘工具方法就不看了,先是Time。

Time

  类本身的说明在上一篇有,这里就去掉了。

class V8_BASE_EXPORT Time final : public time_internal::TimeBase<Time> {
public:
// Contains the nullptr time. Use Time::Now() to get the current time.
constexpr Time() : TimeBase() {} // Returns the current time. Watch out, the system might adjust its clock
// in which case time will actually go backwards. We don't guarantee that
// times are increasing, or that two calls to Now() won't be the same.
static Time Now(); // Returns the current time. Same as Now() except that this function always
// uses system time so that there are no discrepancies between the returned
// time and system time even on virtual environments including our test bot.
// For timing sensitive unittests, this function should be used.
static Time NowFromSystemTime(); // ...
};

  从注释可知,这里的Now是返回国际时间戳的通用方法,但是操作系统可能会对返回值做修正,所以是有一定风险的。第二个NowFromSystemTime使用的系统时间比较准确,求精确的情况下考虑使用这一个。

  但是在mac上,这两个方法是一样的。

#elif V8_OS_POSIX

Time Time::Now() {
// ...
} Time Time::NowFromSystemTime() {
return Now();
}

  这就很蠢了,可能是该操作系统不存在修正时间戳的情况,所以没必要分辨这两个方法了。

  所以对于两种方式的解析就变成了一个,集中来看Now的实现。

// #ifndef _STRUCT_TIMEVAL
// #define _STRUCT_TIMEVAL struct timeval
// _STRUCT_TIMEVAL
// {
// __darwin_time_t tv_sec; /* seconds */
// __darwin_suseconds_t tv_usec; /* and microseconds */
// }; Time Time::Now() {
// 内置结构体 见上面
struct timeval tv;
// Linux内置时间函数
int result = gettimeofday(&tv, nullptr);
// 返回值检测
DCHECK_EQ(, result);
USE(result);
return FromTimeval(tv);
}

  这里的用的都是Linux内置的方法,timeval结构体专门用来获取返回的时间,可以精确到微秒,也就是秒/毫秒/微秒的精度。

  结构体两部分分别保存当前时间戳的秒部分、微秒部分,类型均为long,下面用一个简单例子来展示。

int main() {
struct timeval tv;
gettimeofday(&tv, nullptr);
cout << "current seconds is " << tv.tv_sec << endl;
cout << "current microseconds is " <<tv.tv_usec << endl;
}

  在浏览器下面同时用Date.now()做一个对比,由于还是有一定的时间差,所以微秒部分肯定对不上的。

  两者输出对比如下。

  在秒的部分完全对上了,微秒那块就别在意了,我可没有神手速。

  这样,就通过系统API得到了当前时间戳,下面就是对两个部分做一个处理。

Time Time::FromTimeval(struct timeval tv) {
// 1秒 = 1000 * 1000微秒 这里做的合法性检测
DCHECK_GE(tv.tv_usec, );
DCHECK(tv.tv_usec < static_cast<suseconds_t>(kMicrosecondsPerSecond));
// 当秒、微秒都返回0 返回默认构造类 如下
// constexpr Time() : TimeBase(0) {}
if (tv.tv_usec == && tv.tv_sec == ) {
return Time();
}
// 如果返回值达到了最大值 则返回最大值 max也是内置方法
if (tv.tv_usec == static_cast<suseconds_t>(kMicrosecondsPerSecond - ) &&
tv.tv_sec == std::numeric_limits<time_t>::max()) {
return Max();
}
// 这里返回微秒单位的数值
return Time(tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec);
}

  比较简单,看一下注释就懂了,最后返回的是以微秒为单位的一个长整数,而JS中的Date.now()返回的则是毫秒单位,略有不同。

TimeTicks

class V8_BASE_EXPORT TimeTicks final : public time_internal::TimeBase<TimeTicks> {
public:
constexpr TimeTicks() : TimeBase() {}
static TimeTicks Now();
static TimeTicks HighResolutionNow();
static bool IsHighResolution(); private:
friend class time_internal::TimeBase<TimeTicks>; explicit constexpr TimeTicks(int64_t ticks) : TimeBase(ticks) {}
};

  这个类看看就好了,跟上面那个类似,也有两个方法,一个是更精确的。

  然而,两个方法也是一个,在mac上不存在精细度(windows上都有区别,下篇搞),V8在内部直接写了如下注释。

#error platform does not implement TimeTicks::HighResolutionNow.

  所以,只看Now的实现。

struct mach_timebase_info {
uint32_t numer; // 分子
uint32_t denom; // 分母
}; TimeTicks TimeTicks::Now() {
int64_t ticks;
static struct mach_timebase_info info;
if (info.denom == ) {
kern_return_t result = mach_timebase_info(&info);
}
ticks = (mach_absolute_time() / Time::kNanosecondsPerMicrosecond * info.numer / info.denom);
// Make sure we never return 0 here.
return TimeTicks(ticks + );
}

  这里涉及2个内置方法和1个内置结构体,挨个介绍一下。

  • mach_timebase_info结构体作为参数传入同名函数
  • mach_timebase_info方法返回两个因子,将返回的分子除以分母可以得到一个基准参数(找不到Linux的官方API文档,还是windows好啊),具体解释有兴趣可以去查看
  • mach_absolute_time方法返回一个系统从启动开始保持运行的一个绝对时间,参考windows的QPC,单位为纳秒

  唯一有价值的就是那个单位,由于返回的绝对时间单位是纳秒,所以需要除以TimeConstants里面的常数,最后与基准参数相乘,最终得到一个硬件时间戳。

  本地做一个实验。

int main() {
static struct mach_timebase_info info;
mach_timebase_info(&info);
cout << "numer is " << info.numer << endl;
cout << "denom is " << info.denom << endl;
cout << "absolute time is " << mach_absolute_time() << endl;
cout << "current timestamp is " << (info.numer / info.denom) * (mach_absolute_time() * 1e-) << endl;
}

  这样得到最终的结果理论上就是我mac电脑的活跃秒数。

  7000秒,也就是大约2个小时吧,看来还是很准确的,有兴趣的可以自行实验。

  下一篇换windows,apple的apidoc真是一坨屎,根本跟微软没法比。

深入V8引擎-Time核心方法之mac篇的更多相关文章

  1. 深入V8引擎-Time核心方法之win篇(2)

    这一篇讲windows系统下TimeTicks的实现. 对于tick,V8写了相当长的一段discussion来讨论windows系统上计数的三种实现方法以及各自的优劣,注释在time.cc的572行 ...

  2. 深入V8引擎-Time核心方法之win篇(1)

    上一篇的源码看得十分无趣,官方文档跟黑心棉一样渣. 这一篇讲讲windows操作系统上的时间戳实现,由于类的声明,方法解释上一篇都贴过了,所以这次直接上对应版本的代码. windows与mac很不一样 ...

  3. 深入V8引擎-默认Platform之mac篇(2)

    先说结论,V8引擎在默认Platform中初始化的这个线程是用于处理类似于setTimeout的延时任务. 另外附一些图,包括继承树.关键属性归属.纯逻辑工作流程,对代码木得兴趣的看完图可以X掉了. ...

  4. 浅谈Chrome V8引擎中的垃圾回收机制

    垃圾回收器 JavaScript的垃圾回收器 JavaScript使用垃圾回收机制来自动管理内存.垃圾回收是一把双刃剑,其好处是可以大幅简化程序的内存管理代码,降低程序员的负担,减少因 长时间运转而带 ...

  5. 浅谈V8引擎中的垃圾回收机制

    最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...

  6. 深入出不来nodejs源码-V8引擎初探

    原本打算是把node源码看得差不多了再去深入V8的,但是这两者基本上没办法分开讲. 与express是基于node的封装不同,node是基于V8的一个应用,源码内容已经渗透到V8层面,因此这章简述一下 ...

  7. 深入V8引擎-初始化默认Platform

    本来寻思着写一篇"'Hello' + ', World'"是怎么从JS代码编译然后输出的,然而compile过程的复杂性远超我的想象,强上怕会走火入魔,还是老老实实先回家种田,找点 ...

  8. Chrome V8引擎系列随笔 (1):Math.Random()函数概览

    先让大家来看一幅图,这幅图是V8引擎4.7版本和4.9版本Math.Random()函数的值的分布图,我可以这么理解 .从下图中,也许你会认为这是个二维码?其实这幅图告诉我们一个道理,第二张图的点的分 ...

  9. (译)V8引擎介绍

    V8是什么? V8是谷歌在德国研发中心开发的一个JavaScript引擎.开源并且用C++实现.可以用于运行于客户端和服务端的Javascript程序. V8设计的初衷是为了提高浏览器上JavaScr ...

随机推荐

  1. $Codeforces\; Round\; 504\; (Div.2)$

    宾馆的\(\rm{wifi}\)也太不好了,蹭的\(ZZC\)的热点才打的比赛(感谢\(ZZC\)) 日常掉rating-- 我现在是个\(\color{green}{pupil}\)-- 因为我菜, ...

  2. Authentication token manipulation error报错解决办法

    Authentication token manipulation error报错解决办法 #参考http://blog.163.com/junwu_lb/blog/static/1916798920 ...

  3. ios之UITabelViewCell的自定义(代码实现)

    在用到UITableVIew的时候,经常会自定义每行的Cell 在IOS控件UITableView详解中的下面代码修改部分代码就可以实现自定义的Cell了 [cpp] view plaincopy - ...

  4. 自写小函数处理 javascript 0.3*0.2 浮点类型相乘问题

    const reg = /^([-+]?)([0-9]+)\.([0-9]*)$/; // 判断是不是浮点数 const isFloat = function(number){ return reg. ...

  5. C++系统学习之二:字符串

    上一篇文章主要学习的是C++的基本类型,它们是C++语言直接定义的,它们体现了计算机硬件本身具备的能力.而本篇文章将主要学习内置类型之外的标准库所定义的类型,分别是string和vector,此外还将 ...

  6. 【搜索 ex-BFS】bzoj2346: [Baltic 2011]Lamp

    关于图中边权非零即一的宽度优先搜索 Description 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组 ...

  7. MySQL 查询优化之 Index Merge

    MySQL 查询优化之 Index Merge Index Merge Intersection 访问算法 Index Merge Union 访问算法 Index Merge Sort-Union ...

  8. nginx 无法加载css/js图片等文件 404 not fund

    刚配置Nginx反向代理,Nginx可能会出现无法加载css.js或者图片等文件,这里需要在配置文件*.conf里面加上如下配置项. location ~ .*\.(js|css|png|jpg)$ ...

  9. ACM训练联盟周赛 K. Teemo's reunited

    Teemo likes to drink raspberry juice.  He even spent some of his spare time tomake the raspberry jui ...

  10. HDU 3516 DP 四边形不等式优化 Tree Construction

    设d(i, j)为连通第i个点到第j个点的树的最小长度,则有状态转移方程: d(i, j) = min{ d(i, k) + d(k + 1, j) + p[k].y - p[j].y + p[k+1 ...