JavaScript 開發者所須要知道的 V8(一):V8 In NodeJS

歡迎來個人博客閱讀:「JavaScript 開發者所須要知道的 V8(一):V8 In NodeJS」javascript

Motivation

JavaScript 是一款擁有「自動垃圾回收」功能的編程語言。
市面上具備這樣功能的語言,通常都是擁有相對應的虛擬機的,像 Java的JVM ,C#的CLR ,PHP的Zend。
虛擬機通常實現了代碼解析,內存的管理、佈局、垃圾回收等功能。
不像C/C++這種沒有虛擬機的語言,它們須要手動管理內存。
C/C++語言編譯後的文件,是能夠直接運行的。html

我認爲學習一門開發語言,除了知道一些語法上的使用,各類API的調用之外。學習相應的虛擬機也是頗有必要的。而 JavaScript 因爲其特殊的歷史緣由,並非只有 V8 一個引擎。可是目前 V8 它是業界最優秀的 JavaScript 引擎,也就成爲了一個學習樣本。java

現在的 JavaScript 不只僅是用在瀏覽器端了,也由於 NodeJS 的關係得以在服務器端運行。和瀏覽器端不一樣的地方在於服務器端對資源的敏感性是很高的。當業務規模大了,併發量上來了,一些很細小的問題會放大。這時候一些小小的內存泄漏,都會釀造災難。node

因此做爲一個 JavaScript 開發者,搞清楚從敲入 console.log('hello world'),直到後面交由CPU執行的中間過程是很重要的。
這也對如何用 JavaScript 這門鬆散的語言編寫出高質量的代碼是具備指導做用的。git

想真正作到 JavaScript 全棧,路漫漫其修遠兮。github

V8 概述

V8 做爲一個 JavaScript 引擎,最初是服役於 Google Chrome 瀏覽器的。它隨着 Chrome 的初版發佈而發佈以及開源。如今它除了 Chrome 瀏覽器,已經有不少其餘的使用者了。諸如 NodeJS、MongoDB、CouchDB 等。編程

JavaScript 做爲 Prototype-Based Language , 基於它使用 Prototype 繼承的特徵,V8 使用了直譯的方式,即把 JavaScript 代碼直接編譯成機器碼( Machine Code, 有些地方也叫 Native Code ),而後直接交由硬件執行。
與傳統的「編譯-解析-執行」的流程不一樣,V8 處理 JavaScript,並無二進制碼或其餘的中間碼。數組

簡單來講,V8主要工做就是:「把 JavaScript 直譯成機器碼,而後運行」
但這中間,每每是一個複雜的過程,它須要處理不少的難題,諸如:瀏覽器

  1. 編譯優化服務器

  2. 內存管理

  3. 垃圾回收

我寫的這一系列文章,也是從這三個大點來出發,解讀V8針對這些內容的處理。

V8 In NodeJS

NodeJS源碼小覽

NodeJS,是怎麼引入V8的?
咱們關注Node的源碼目錄:

.
├── ...
├── deps
│   ├── ...
│   ├── v8
│   ├── ...
├── ...
├── lib
│   ├── ...
│   ├── buffer.js
│   ├── child_process.js
│   ├── console.js
│   ├── ...
├── node -> out/Release/node
├── ...
├── out
│   ├── ...
│   ├── Release
|         ├── node
|         ├── node.d
|         ├── obj
|             └── gen
|                 ├── ...
|                 ├── node_natives.h
|                 ├── ...
│   ├── ...
├── src
│   ├── ...
│   ├── debug-agent.cc
│   ├── debug-agent.h
│   ├── env-inl.h
│   ├── env.cc
│   ├── ...
├── 
...

須要關注的幾個目錄和文件:

/deps/v8:這裏是V8源碼所在文件夾,你會發現裏面的目錄結構跟V8源碼十分類似。NodeJS除了移植V8源碼,還在增添了一些內容。

/src:由C/C++編寫的核心模塊所在文件夾,由C/C++編寫的這部分模塊被稱爲「Builtin Module」

/lib:由JavaScript編寫的核心模塊所在文件夾,這部分被稱爲「Native Code」,在編譯Node源碼的時候,會採用V8附帶的js2c.py工具,把全部內置的JavaScript代碼轉換成C++裏面的數組,生成out/Release/obj/gen/node_natives.h文件。有些 Native Module 須要藉助於 Builtin Module 實現背後的功能。

/out:該目錄是Node源碼編譯(命令行運行make)後生成的目錄,裏面包含了Node的可執行文件。當在命令行中鍵入node xxx.js,實際就是運行了out/Release/node文件。

來張圖說明一下V8在Node運行時的總體過程。

v8 in nodejs.png

Node在啓動的時候,就已經把 Native Module,Builtin Module 加載到內存裏面了。後來的 JavaScript 代碼,就須要經過 V8 進行動態編譯解析運行。

查看V8版本號

NodeJS的進步與V8息息相關,關注每一個NodeJS版本所對應的V8版本,能夠增強該版本新功能的理解和由來。

在NodeJS中,經過process.versions能夠查看NodeJS依賴模塊的版本號,V8就包含其中。

例如,我運行的 v7.0.0的NodeJS:

$ node
> process.versions
{ http_parser: '2.7.0',
  node: '8.0.0-pre',
  v8: '5.4.500.36',
  uv: '1.10.0',
  zlib: '1.2.8',
  ares: '1.10.1-DEV',
  modules: '51',
  openssl: '1.0.2j',
  icu: '58.1',
  unicode: '9.0',
  cldr: '30.0.2',
  tz: '2016g' }

NodeJS與V8的纏綿

  • 2008年9月,V8 的第一個版本隨着 Chrome 的初版本發佈。

  • 2009年5月,NodeJS 的第一個版本由 Ryan Dahl 在 GitHub 上發佈。

  • 2010年12月,官方公佈 V8 的名爲 Crankshaft 的優化編譯器,與原來的 Full Compiler 一塊兒工做,聲稱較2008年版本提升50%性能。

  • 2014年12月, io.js 從久久不更新的 NodeJS 分出來支,而且引入最新的 V8 ,這時候 NodeJS 處於0.12.17版本。

  • 2015年2月,NodeJS基金宣佈NodeJS(v0.12)和io.js(v3.3)合併,合併版本在將來發布。

  • 2015年7月7日,官方公佈又一個新的名爲TurBoFan的優化編譯器,主要提供ES6的新語法,以及提升性能。並代表該編譯器最終目標是所有替代Crankshaft編譯器

  • 2015年7月17日,官方發佈集成TurboFan的V8版本(v4.5)

  • 2015年9月08日,NodeJS緊跟着發佈了與io.js的合併版本(V4.0),引入最新的V8,給開發者們帶來了最新的ES6語法,以及性能上的提升。

  • 2015年8月28日,V8發佈v4.6版本

  • 2015年10月29日,NodeJS發佈V5.0.0版本

  • 2016年3月15日,V8發佈v5.0版本

  • 2016年4月26日,NodeJS發佈V6.0.0版本

  • 2016年7月18日,V8發佈v5.3版本,新增名爲Ignition的解析器(Interpreter),跟原有的優化編譯器(Crankshaft and TurboFan)進行串聯工做,提供了更加優化的內存使用方案,主要針對於低內存的Android設備,並稱在將來會普及到全平臺。

  • 2016年10月25日,NodeJS發佈v7.0.0版本

  • 截止到今天(2016年11月),NodeJS版本v7.0.0,搭配了v5.4的v8,而官方發佈的最新v8版本是v5.5

回顧整個歷程,因爲NodeJS是搭建在V8之上的,因此NodeJS不少「新增語言特性」和「提升性能」等更新都須要依賴V8的發佈日程。

就像NodeJS和io.js宣佈合併,和真正發佈V4.0版本的中間,還隔了V8的生命歷程一個重大的更新(發佈 TurboFan 編譯器,該編譯器引入了大量的ES6語法支持。)。這個更新直接提供了至關一部分的ES6語法,以及性能上的提升。

總結

本篇主要描述了下面幾點:

  1. 個人寫做動機,理解NodeJS底層,給寫出高質量JavaScript代碼提供指導。

  2. 簡單描述V8的角色,以及主要職責:編譯優化、內存管理、垃圾回收。

  3. 經過NodeJS源碼目錄,以及NodeJS代碼加載過程,來認識V8在這之中的位置。

  4. 羅列NodeJS與V8的歷代迭代版本以及聯繫,強調V8在NodeJS中的地位。

相關文章
相關標籤/搜索