又到了常规的堆砌代码凑文章字数环节,很多API我就直接贴官方的英文释义,个人翻译其实有时候并不是很准确,搞错了甚至会误导,还是尽量自己去理解。

  首先看看入口方法。

std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();

// int类型 thread_pool_size => 0
// 枚举值 idle_task_support => kDisabled
// 枚举值 in_process_stack_dumping => kDisabled
// 类 tracing_controller => NULL
std::unique_ptr<v8::Platform> NewDefaultPlatform(
int thread_pool_size, IdleTaskSupport idle_task_support,
InProcessStackDumping in_process_stack_dumping,
std::unique_ptr<v8::TracingController> tracing_controller) {
// 不会进这里
if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
v8::base::debug::EnableInProcessStackDumping();
} //
std::unique_ptr<DefaultPlatform> platform(new DefaultPlatform(idle_task_support, std::move(tracing_controller)));
//
platform->SetThreadPoolSize(thread_pool_size);
//
platform->EnsureBackgroundTaskRunnerInitialized();
return std::move(platform);
}

  这里比较头疼的是我没找到NewDefaultPlatform方法是在哪里定义的,所以默认参数不知道是什么,只能打断点调试看变量值,已经在注释标注了。

  默认参数情况下,那个if分支是不会进去的,所以无视,后面的三个语句都各自负责了一部门功能,分别是初始化默认Platform对象、设置线程池大小、启动工作线程,分块来看各部分源码。

  第一条语句直接用new构造了一个DefaultPlatform对象,如下,加了一些标注。

//
DefaultPlatform::DefaultPlatform(
IdleTaskSupport idle_task_support,
std::unique_ptr<v8::TracingController> tracing_controller)
: thread_pool_size_(),
idle_task_support_(idle_task_support),
tracing_controller_(std::move(tracing_controller)),
// 1-1
page_allocator_(new v8::base::PageAllocator()),
time_function_for_testing_(nullptr) {
if (!tracing_controller_) {
// 1-2
tracing::TracingController* controller = new tracing::TracingController();
// 1-3
controller->Initialize(nullptr);
// 智能指针替换
tracing_controller_.reset(controller);
}
}

  这是接受两个参数的构造函数,而且DefaultPlatform只有这一个构造函数。除了用给定的2个参数初始化属性,一些其他属性也用默认的参数初始化了,对于0、nullptr这种就不用管,其中比较特殊的是那个page_allocator初始化,上一篇给出的类声明是基类,在V8的命名空间有一个同名的实现类。

class PageAllocator : public ::v8::PageAllocator {
// ...
private:
const size_t allocate_page_size_;
const size_t commit_page_size_;
} PageAllocator::PageAllocator()
: allocate_page_size_(base::OS::AllocatePageSize()),
commit_page_size_(base::OS::CommitPageSize()) {}

  我也是服了V8,弄了个同名的类,第一次看楞了好久。构造函数调用的是OS命名空间的方法,这个命名空间是用来取一些系统参数,调用mac系统上<unistd.h>头文件的一些API,看一下allocate_page_size的初始化就明白了。

size_t OS::AllocatePageSize() {
return static_cast<size_t>(sysconf(_SC_PAGESIZE));
}

  这里用了一个sysconf方法,在其他的很多地方也有使用,官方解释如下。

get configuration information at run time

  当成NODE_ENV来理解就差不多了,也就是一个获取系统配置参数的API,对于PageAllocator的两个属性,官方的解释依次如下。

1、Size of a page in bytes.  Must not be less than 1.
2、memory page size

  两个其实都是page size(内存页大小,关于Linux的内存模型我不太懂,后面有空再去了解),我本地测试了一下,都返回的4096。

  对属性初始化完后,构造函数会继续走代码块里的语句,由于外部传进来的tracing_controller是个NULL,所以这里还需要手动new一个。

TracingController::TracingController() = default;

  然而这个构造函数没啥好讲的,因为是默认构造函数,所以直接跳过了,后面的两步也没什么讲的,reset是智能指针的API,替换管理内容。

  下面是第二条语句,从命名直接能看出来了,就是设置线程池的大小,方法也比较简单暴力了。

//
void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
base::MutexGuard guard(&lock_);
DCHECK_GE(thread_pool_size, );
if (thread_pool_size < ) {
// The number of processors currently online (available) => 4
thread_pool_size = base::SysInfo::NumberOfProcessors() - ;
}
// max(min(8, size), 1)
thread_pool_size_ = std::max(std::min(thread_pool_size, kMaxThreadPoolSize), );
}

  这里实际上也是调用了一个类似于上面的sysconf来获取系统参数,返回的系统处理器数量,由于其中一个要用来作为主线程,所以可用的线程池数量要减一,简单处理一下返回一个size。

  第三条语句内容相当的麻烦,看得我脑子疼,语义上理解就是保证后台线程runner的初始化运行。

  说得简单,由于之前的操作只是初始化了一个空白platform类,算了算线程池的大小,所以剩下的所有实际操作都在这里。大概包含了初始化线程池、生成线程同时分配任务、管理task队列、启动线程等一系列操作,其中的思想倒并不复杂,实际上跟libuv的异步原理相差无几,但是深入源码的每一步还是挺恶心的,下一篇再来搞。

深入V8引擎-默认Platform之mac篇(1)的更多相关文章

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

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

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

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

  3. 深入V8引擎-引擎内部类管理解析

    v8的初始化三部曲,前面花了三篇解决了第一步,由于只是生成了一个对象,第二步就是将其嵌入v8中,先看一下三个步骤. // 生成默认Platform对象 std::unique_ptr<v8::P ...

  4. V8引擎嵌入指南

    如果已读过V8编程入门那你已经熟悉了如句柄(handle).作用域(scope)和上下文(context)之类的关键概念,以及如何将V8引擎作为一个独立的虚拟机来使用.本文将进一步讨论这些概念,并介绍 ...

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

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

  6. V8引擎——详解

    前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...

  7. v8引擎详解

    引用网址: https://blog.csdn.net/swimming_in_it_/article/details/78869549 前言 JavaScript绝对是最火的编程语言之一,一直具有很 ...

  8. 一文搞懂V8引擎的垃圾回收

    引言 作为目前最流行的JavaScript引擎,V8引擎从出现的那一刻起便广泛受到人们的关注,我们知道,JavaScript可以高效地运行在浏览器和Nodejs这两大宿主环境中,也是因为背后有强大的V ...

  9. 探究JS V8引擎下的“数组”底层实现

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/np9Yoo02pEv9n_LCusZn3Q作者:李超 JavaScript 中的数组有很多特性 ...

随机推荐

  1. Django models 单表查询

    从数据库中查询出来的结果一般是一个集合,这个集合叫做 QuerySet 1. 查看Django QuerySet执行的SQL .query.__str__()或 .query属性打印执行的sql语句 ...

  2. shell脚本按当前日期输出日志

    shell脚本基本技能是设置变量,输出信息.如下: sh脚本输出到控制台 将以上脚本保存到test.sh脚本文件中,并赋予可执行权限:sudo chmod +x test.sh 执行脚本:bash t ...

  3. SpringBoot 整合Mybatis操作数据库

    1.引入依赖: <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId> ...

  4. js中对字符串(String)去除空格

    str为要去除空格的字符串: 去除所有空格: str = str.replace(/\s+/g,""); 去除两头空格: str = str.replace(/^\s+|\s+$/ ...

  5. liteos软件定时器(十)

    1 概述 1.1 基本概念 软件定时器,是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数.定时精度与系统Tick时钟的周期有关. 硬件定时器受 ...

  6. [linux] 进程五状态模型

    运行态:该进程正在执行:就绪态:进程做好了准备,只要有机会就开始执行:阻塞态:进程在某些事件发生前不能执行,如I/O 操作完成:新建态:刚刚创建的进程,操作系统还没有把它加入到可执行进程组中.通常是进 ...

  7. django-图形验证码(django-simple-captcha)

    在网站开发的登录页面中,经常会需要使用到图形验证码来验证.在Django中,django-simple-captcha库包提供了图形验证码的使用. django-simple-captcha的安装 p ...

  8. 01-Redis 简单介绍

    Redis 简单介绍 1.Redis 是什么 Redis 是一种基于键值对的 NoSQL 数据库,与很多键值对数据库不同, redis 中的值可以有 string, hash , list , set ...

  9. Codeforces Round #304 (Div. 2)(CF546D) Soldier and Number Game(线性筛)

    题意 给你a,b(1<=b<=a<=5000000)表示a!/b!表示的数,你每次可以对这个数除以x(x>1且x为这个数的因子)使他变成a!/b!/x, 问你最多可以操作多少次 ...

  10. 算法学习day01 栈和队列

    1,设计一个算法利用顺序栈的基本运算判断一个字符串是否是回文 解题思路:      由于回文是从前到后和从后到前读都是一样的,所以只要将待判断的字符串颠倒 然后与原字符串相比较,就可以决定是否是回文了 ...