I'll take a quiet life. A handshake of carbon monoxide.

0%

原创文章,转载请标明出处:Soul Orbit
本文链接地址:ChakraCore学习笔记(三):使用JSRT API (一)

大概了解了ChakraCore的顶层结构和其对应的JSRT API之后,让我们再来看看其他的JSRT API和如何使用它们吧。

为了演示JSRT API,在这一篇里,我们会来尝试如下几件事情:

  1. 注入一个简单的JS API
  2. 简单了解ChakraCore的异常处理
  3. 实现一个简单的API Framework

选择这几个目标的原因是因为——毕竟不管在源码层面使用什么脚本引擎,大家一开始最关注的还是怎么注入自己的API来完成自己想要做的事情呀。

1. Hello World

首先让我们建立一个最简单的程序作为开始吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "stdafx.h"
#include "ChakraCore.h"

int main()
{
JsRuntimeHandle runtime;
JsContextRef context;
JsValueRef result;

JsCreateRuntime(JsRuntimeAttributeNone, nullptr, &runtime);
JsCreateContext(runtime, &context);
JsSetCurrentContext(context);

JsSetCurrentContext(JS_INVALID_REFERENCE);
JsDisposeRuntime(runtime);

return 0;
}
Read more »

原创文章,转载请标明出处:Soul Orbit
本文链接地址:ChakraCore学习笔记(二):从Hello World看ChakraCore顶层数据结构

上一篇里我们已经大概了解了如何编译和使用ChakraCore,现在我们来仔细看一看ChakraCore的Hello World,以此出发来了解一下ChakraCore的主体结构大概长的什么样子吧。

1. 代码结构

在看代码之前,先让我们来大概看一眼ChakraCore的代码结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.
├─bin :: 生成可执行文件的工程,比如ChakraCore.dll
├─Build :: 各个平台下的makefile或项目工程
├─jenkins :: 给jenkins使用的检查和编译的脚本
├─lib :: ChakraCore主要实现
│ ├─Backend :: JIT的实现
│ ├─Common :: ChakraCore的基础库
│ │ ├─Codex :: 编码转换,比如UTF-8
│ │ ├─Common :: 基础类,比较杂,比如一些和整型相关的数学计算,时间处理之类的
│ │ ├─Core :: 也比较杂,和Common的区别在于这里面一般和ChakraCore的功能相关,比如配置文件等等
│ │ ├─DataStructures :: 基础数据结构,比如数组,链表,HashMap等等
│ │ ├─Exceptions :: 常用异常
│ │ ├─Memory :: 内存管理,GC
│ │ ├─PlaceHolder :: 啊……EXO ME?
│ │ ├─PlatformAgnostic :: 和平台相关的信息的封装,但是这里面只有定义,实现不在这
│ │ └─Util :: 啊……EXO ME?
│ ├─JITClient :: 进程外JIT的客户端
│ ├─JITIDL :: 进程外JIT的协议,IDL定义
│ ├─JITServer :: 进程外JIT的服务端
│ ├─Jsrt :: Jsrt API,其本身都比较简单,主要是用来将ChakraCore内部结构合理的暴露出来
│ ├─Parser :: JavaScript Parser
│ ├─Runtime :: Runtime,ChakraCore最关键的部分之一
│ │ ├─Base :: Runtime中的顶层数据结构,比如我们马上会提到的ThreadContext和ScriptContext
│ │ ├─ByteCode :: ByteCode相关的实现
│ │ ├─Debug :: 用于支持调试的类
│ │ ├─Language :: 比较杂,和JavaScript语言相关但又不太好归类的部分
│ │ ├─Library :: JavaScript对象模型的实现,从基本的bool,int,map到高级的regex和promise
│ │ ├─Math :: 计算相关,加减乘除等等
│ │ ├─PlatformAgnostic :: 平台相关的实现
│ │ └─Types :: 用来实现对象模型的基础类型,比如抽象的Type和RecylableObject
│ └─WasmReader :: WebAssembly加载器
├─manifests :: 用于定义ETW Events的manifest
├─pal :: 一个C标准库的实现,可以使用USING_PAL_STDLIB宏来启用
├─test :: 测试
└─tools :: 一些小工具

2. Runtime和执行上下文(Execution context)

从Hello World中我们可以看到,如果我们需要ChakraCore来运行一段JS脚本,我们至少需要创建两样东西:JsRuntimeHandle(Runtime)和JsContextRef(执行上下文,execution context),这也是ChakraCore一开始最重要的两个概念。

2.1. Runtime:JsrtRuntime

Runtime这个词一听就知道非常重要,在这里也一样,它表示一个完整的用来支持JavaScript运行的环境,它具有自己独立的堆,编译器,JIT的线程和垃圾回收的线程。

在ChakraCore里,Runtime和线程是紧密相关的,但是他们并不是一对一的,一个线程上可以存在多个Runtime,但在任意时刻都只允许存在一个活动的Runtime,而一个Runtime在任意时刻也只能运行在一个线程上,不过如果一个Runtime没有被任何地方使用,比如正在执行一段JS,那么你可以安全地在另一个没有被占用的线程上调用它。

在JSRT API里,JsRuntimeHandle用于表示一个Runtime,如果我们进入JsCreateRuntime这个API,我们就会发现它其实就是其真正Runtime的实现——JsrtRuntime的内存地址。

Read more »

原创文章,转载请标明出处:Soul Orbit
本文链接地址:ChakraCore学习笔记(一):在Windows上编译ChakraCore

Chakra是Edge浏览器中的JavaScript引擎,在2016年6月份,我看到Edge的博客说,Chakra的benchmark已经超越了Chrome v8,而且看数据还不是一点半点,这件事情让我又惊讶又激动,因为这确实不容易啊,所以当时就非常好奇Chakra是怎么实现的,可是一直都抽不出时间来好好读读代码,直到现在。正好博客也已经搬迁完毕了,所以在一边阅读的过程中,正好一边写一点东西,做个笔记吧。

1. Chakra vs ChakraCore

16年年初,Chakra的源代码被开源放在了github上,项目名叫ChakraCore:https://github.com/Microsoft/ChakraCore

虽然ChakraCore具有几乎所有Chakra的功能,但是它并不是Chakra,他们之间的差别主要有两个:

  1. Chakra中有一套绑定接口用于支持浏览器和UAP,这套接口并没有暴露在ChakraCore中,但是ChakraCore提供了另外一套公开的接口JSRT用来完成同样的功能。
  2. Chakra中有一套用于支持调试的基于COM的接口,但是除了Windows以外的平台并没有COM,所以Chakra正在开发一套新的基于Json接口来支持调试

下面这张来自ChakraCore Github的图很好的说明了ChakraCore和Chakra的区别:
chakracore_componentization

随着时间的发展,现在ChakraCore已经可以在Windows,Linux和Mac上编译和运行。这个我觉得是很有意义的,因为这使得Chakra不是仅仅为了Edge而存在,而是能更好的和整个社区一起发展,比如,现在ChakraCore已经能够支持nodejs,当然我们也可以用它来做别的事情,比如做游戏的脚本引擎等等。

Read more »

原创文章,转载请标明出处:Soul Orbit
本文链接地址:为Hexo博客标题自动添加序号:hexo-heading-index

在Hexo更新到Hexo 3之后,它提供了一个函数给皮肤用来生成文章目录,不过虽然这个函数提供了一个参数可以在文章目录中输出标题序号,但是文章内部的标题却没有添加,所以阅读文章本身并不是那么直观。为了解决这个问题,我写了一个插件来解决这个问题:hexo-heading-index。

1. 安装

和其他插件一样,hexo-heading-index的安装非常直接:

1
npm install hexo-heading-index --save

2. 配置

hexo-heading-index的配置都放在了_config.yml中,但是可能没有那么的直观,所以我们先来看一个例子:

1
2
3
4
5
6
heading_index:
enable: true
index_styles: "{1} {1} {1} {1} {1} {1}"
connector: "."
global_prefix: ""
global_suffix: ". "

这个配置会让我们生成如”1.2.3.4. “这样的序号。为什么呢?

Read more »

原创文章,转载请标明出处:Soul Orbit
本文链接地址:为Hexo博客添加文章链接:hexo-tag-post-link

文章链接是写博客时一个非常常用的东西,因为如果每次写博客都需要在文章前后加上一个几乎格式一模一样的东西,还是很烦人的,特别如果你突然决定改变文章的永久链接,那么就更加烦人了,因为默认在Hexo里面,我们需要一篇文章一篇文章的把所有的文章链接改了(虽然这种情况我们需要尽量避免),所以这里我写了一个小插件来帮我们简化这个步骤————hexo-tag-post-link。

项目地址:https://github.com/r12f/hexo-tag-post-link

1. 安装

和其他的hexo插件一样,hexo-tag-post-link安装起来十分简单,只需要在博客目录下执行如下命令即可:

1
npm install hexo-tag-post-link --save

2. 使用方法

2.1. 插入标签

hexo-tag-post-link使用起来非常的直观,我们需要做的主要就是在博客里面你喜欢的位置加入一个标签,格式如下:

1
{% post_link <template_name> %}

这里template_name是我们指定的模板名字,比如,如果我们的模板名字叫做header,那么我们只需要插入如下标签:

1
{% post_link header %}
Read more »

原创文章,转载请标明出处:Soul Orbit
本文链接地址:使用github pages和hexo搭建静态博客

终于把博客搬迁了个大概,虽然已经有不少文章在说怎么用github和hexo搭建博客了,但是真正在做的时候还是依然觉得走了不少弯路,所以决定还是写一篇文章做个记录吧。

1. 事先准备

要使用Hexo,在开始之前,我们需要安装nodejs和git。如何安装这里就不再赘述了,我比较推荐使用chocolatey。至于为什么?方便啊!

chocolatey的工程在这里:https://chocolatey.org/,安装需要在powershell下,但是安装完之后就可以在cmd下执行了。

1
2
3
4
5
:: 安装git
choco install git

:: 安装nodejs
choco install nodejs
Read more »

最后还是打算把博客迁移到github上来托管了,自己管理主机是挺好玩,但是实在没时间折腾了。。。没有CDN,不是墙外加载慢,就是墙内加载慢,而且还时不时的有人来攻击一下。。。不明白呀,我一个小博客,里面能有啥。。。现在全部换成静态网页挂在github上,CDN也有了,也不用怎么担心被攻击了~

Hexo确实相当好使啊,而且用Markdown写博客,用git管理实在是太对我的口味了,现在麻烦的事情还有两个,一个是设置CI,自己老在本机编译实在是太土了;另外就是怎么把老的内容迁移过来,这么多年下来写的杂七杂八虽然现在看起来简直就是黑历史,但是就这么扔掉还是怪可惜的。。。再折腾一下,看看怎么才能解决Hexo导入Wordpress遇到的各种异常好了。

原创文章,转载请标明出处:Soul Orbit
本文链接地址:Windows命令行的“.bashrc”

自从上次换了工作,新工作,新环境,新文化,新语言,适应起来果然还是需要时间,一段时间忙的焦头烂额,博客就再次长草了,这次先来篇简单的文章除除草。

之前使用Linux的时候觉得有样东西特别的方便——.bashrc,每次打开命令行这个文件都会被加载,这样你就可以把你常用的命令放在这个文件里面,从而简化操作。那Windows下,有没有类似的东西呢?

当然是有的,虽然没有Linux下那么的直接,有一个固定的文件,但是在Windows下可以通过注册表来指定加载命令行时需要先加载什么文件。只需要在运行在管理员模式下的命令行中运行如下命令即可:

1
reg add "HKLM\Software\Microsoft\Command Processor" /v "AutoRun" /t REG_SZ /d "<file path>" /f

举个栗子,我们创建一个cmd-init.cmd,用来在启动命令行时设置一个环境变量:

1
2
3
echo @echo off > C:\Users\Riff\config\cmd-init.cmd
echo set test=1 >> C:\Users\Riff\config\cmd-init.cmd
reg add "HKLM\Software\Microsoft\Command Processor" /v "AutoRun" /t REG_SZ /d "C:\Users\Riff\config\cmd-init.cmd" /f

接下来,我们启动命令行之后,就可以输出这个环境变量了:
cmd-init-result

原创文章,转载请标明出处:Soul Orbit
本文链接地址:WPA入门 (三) —— 千变万化的图表

在前面的两篇文章里,我们已经使用WPA的多个图表找到了两个平时经常遇到的问题的真正原因,但是实际上WPA的图表功能远比我们看上去的强大。这一篇,我们来说一些只和图表有关的内容吧,也许这些内容看上去比较乱,而且没有那么有直接的用处,但是也许通过查看经过你自己调整后的图表,你能更好的了解系统里面发生的事情。

1. 数据表(Data table)

数据表是WPA中非常重要的部分,经过解析后的数据会被存放在各个表中,再通过一定的规则生成各种图来更加直观的展示表格中的数据。在WPA里面,所有的数据表都可以通过Graph Explorer来访问。

和普通的表格一样,数据表中的原始数据只是一行一行的记录,但是这样的数据对我们来说非常的难理解,所以为了方便大家更加容易理解这些数据,在数据表中,WPA通过一根黄线和一根蓝线,将表格分为三种不同的区域,并将数据按照我们的需要组织起来,这三个区域分别是:

  • 关键字(Key Area):这部分在黄线之前,放在这个区域里面的列,如果具有相同的值,会被聚合起来变成一条记录,方便我们查看到底有多少类记录,其数据总量是多少,当然,我们也可以展开被聚合的记录来看里面都有哪些具体的记录。另外这部分还会被当作绘制图形时的分组。
  • 数据区(Data Area):这部分在黄线和蓝线的中间,放在这个区域里面的列不会被聚合,展开时所有的记录会和普通的表一样被平铺开来。
  • 绘图区(Graphing Element Area):这部分在蓝线之后,放在这个区域里面的列会被用来绘制当前表格对应的图形。

现在让我们再打开第一篇中我们使用过的Trace,查看Disk IO,重新看看我们已经看过的数据表吧。
wpa-disk-io-default-view

Read more »

原创文章,转载请标明出处:Soul Orbit
本文链接地址:WPA入门(二) —— 分析线程上的等待

上回我们说道记事本怒开大文件,WPA奋勇显神威。通过CPU Sampling Graph和Disk IO Graph,我们很快的定位到了记事本打开大文件缓慢的真正原因。但是就和硬盘里和生活中的女神们一样,现实往往都是残酷的。很多时候不是程序本身消耗了很多的CPU和磁盘资源,最后导致了程序运行的缓慢,甚至我们通过任务管理器查看,会发现CPU,硬盘的使用其实都不高,似乎整个系统是空闲的,但是却就是不干活,这又是为什么呢?这一次,让我们来看一个稍稍复杂一点点的问题吧。

1. 线程状态

为了让我们更加好的理解接下来的内容,首先,我们需要先补充一点和Windows下线程调度相关的背景知识,当然如果你已经知道了,可以跳过这一节。

Windows下线程在被调度的过程中,如性能相关的状态主要有三个:

  • 运行中(Running):该线程正在运行中。
  • 就绪中(Ready):该线程已经可以运行了,但是暂时还没有得到CPU。
  • 等待中(Waiting):该线程正在等待某个资源,暂时还无法运行。

他们之间可以相互转化,其状态转化图和转化原因如下:
thread-state

Read more »