【譯文】NginScript – 為什么我們要實現自己的JS引擎?
在上周的nginx.conf 2015用戶大會上,我們發布了全新的JavaScript引擎nginscript的預覽版。歷史上,JavaScript語言已經應用在許多方面,首先是作為客戶端腳本,然后又被用于服務器后臺開發。至于nginscript,我們要介紹的是第一種"代理端"的使用情況,用于滿足我們在會上提出的一系列獨特的要求。消息公布后,許多人對我們決定要實現一個新的JavaScript引擎,而不是使用V8,SpiderMonkey,或其他的已有引擎而感到好奇,所以這篇文章用于解釋我們為什么這么做。
我們正在做什么?
我們正在編寫自己的JavaScript引擎,稱為nginscript。nginscript目前支持解析器ECMAScript 5的一個子集(我們將在未來進行擴展),采用基于寄存器的虛擬機(VM),運行時將把代碼編譯成字節碼,同時支持 nginx和nginx plus。在目前的預覽階段,nginx可以編譯JavaScript代碼并用在兩個場景:產生nginx的配置,或者在nginx執行階段生成內容。未來的版本將支持更多的使用場景。
為什么要創建自己的JavaScript運行時?
Nginx有一些特別的需求導致我們要去創造屬于我們自己的引擎。為了擴展請求應的處理流程,我們需要nginx在處理一個請求時可以運行nginscript片段。我們不尋求創造一個后端JavaScript應用程序執行環境–因為Node.js已經做的很好。目前的JavaScript引擎被設計為運行在一個Web瀏覽器中,他們依靠垃圾收集器的管理內存。如果耗盡內存,JavaScript VM會異常退出;這種行為對于瀏覽器是可以容忍的。但是對于持有數千個連接的服務器卻不行,總的來說,專門為瀏覽器設計的引擎不適合服務器,包括v8,SpiderMonkey它們沒有供簡單的方法來控制執行(即預防奔潰和恢復虛擬機的機制),同時支持JIT的能力有限。我們希望能有一種引擎將nginscript的腳本簡單并快速的執行。同時,由此產生的狀態被保存在虛擬機外部。因為腳本簡單,所以全面支持JavaScript語言沒有必要。同時,nginx已經擁有非常精細的事件驅動架構,我們不想nginx的性能受到垃圾收器的影響。
相反,我們正在創建一個非常簡單的引擎以滿足我們的要求:
架構 – 使用單線程,字節碼的執行部分將會非常快速。為每個請求分配虛擬機。因為沒有復雜的狀態需要初始化,這種簡單的虛擬機可以快速啟動,同時使用簡單的緩存池管理內存。這種內存管理方案,無需跟蹤和釋放單個對象或使用垃圾回收器,可以大大提高性能。
輔助功能 –Nginx實現了許多內置操作。例如,復雜的數學運算,哈希函數,當nginscript與nginx結合時,這些操作也會是本地的。你可以使用nginscript以編程的方式來驅動nginx的本地方法。
和nginx配合 – nginx的事件驅動模型可以用于調度nginscript VMS的執行。當一個nginscript正在執行阻塞操作(如讀取網絡數據),nginx可以暫停該VM的執行,當該VM的事件完成后再恢復。這意味著你可以在編寫一個簡單的腳本, nginx會調度腳本不造成阻塞。最后,用我們自己的引擎,我們可以保證API統一,同時確保我們的VM和nginx支持的平臺范圍一致。
關于性能
現在談論性能還過早,目前我們正在專注于功能的實現。nginscript編譯為內部的字節碼并且運行在一個基于寄存器的虛擬機;這種機制使得它和其他解釋性語言(PHP,Ruby,等等)性能相當。所以為了提高性能,我們想在一些地方增加JIT編譯,但這可能會限制支持的平臺范圍。nginscript只是被設計用來執行一些簡單的內部腳本,我們不想讓它來執行計算密集型操作,因為nginx內部基于C語言的模塊已經解決這個問題。
nginscript目前處于其發展的早期階段,我們稱當前版本是"預覽"版。我們將重點放在核心語言的實現(如增加閉包),并實施許多內置的JavaScript對象(日期,數學,等等)。
我們還將重點放在如何整合資源,比如nginx的配置如何集成腳本,在哪些方面nginscript可以訪問和控制nginx內部?如何在腳本之間共享數據,以及跨集群?用戶如何調試nginscript腳本?
對于長時間運行的腳本(如WebSocket),我們甚至可以添加一個垃圾收集器,但那是在未來很久以后。
對于nginscript未來如何發展目前還沒有定論。我們希望得到您的反饋。請在我們的郵件列表中分享您的想法和見解,我們將共同開發這個功能。謝謝你。
來自:http://www.cnblogs.com/AlwaysFixBug/p/4857559.html</span></span>