Linus Torvalds是個(gè)非常厲害的程序員,因?yàn)樗袃蓚€(gè)名揚(yáng)天下的作品:Linux和Git。
如果單論技術(shù)能力,有一個(gè)人,也許比Linus更強(qiáng)。
我在看他主頁(yè)項(xiàng)目列表的時(shí)候,感覺(jué)頭都炸了。
他開(kāi)發(fā)了著名的模擬器QEMU和音視頻處理庫(kù)FFmpeg,僅僅是這兩項(xiàng)就超越絕大部分程序員了,他還寫(xiě)過(guò)C編譯器,OpenGL實(shí)現(xiàn),LTE軟基站,JS引擎,讓Linux在瀏覽器中跑起來(lái),甚至還創(chuàng)造了計(jì)算圓周率的世界紀(jì)錄......
也就是說(shuō),這位老兄在操作系統(tǒng)、模擬器、多媒體、計(jì)算機(jī)圖形學(xué)、編譯器、編程語(yǔ)言、通信、甚至數(shù)學(xué)等領(lǐng)域跳來(lái)跳去,一年開(kāi)發(fā)一個(gè)我一輩子都寫(xiě)不出的軟件!
他寫(xiě)的程序還總是比別的程序小幾個(gè)數(shù)量級(jí),快幾個(gè)數(shù)量級(jí)!
這也太變態(tài)了吧?!
不得不承認(rèn),這個(gè)世界上真的有天才的存在。
他就是法國(guó)程序員Fabrice Bellard。
![]()
Bellard還有個(gè)重要的特點(diǎn),寫(xiě)了一個(gè)厲害軟件,開(kāi)創(chuàng)了一個(gè)領(lǐng)域,就把工作交給社區(qū)維護(hù),自己拍拍屁股走人,挑戰(zhàn)另外一個(gè)難題。
這不,最近Fabrice Bellard又出手了,這次他帶來(lái)了一個(gè)叫做MicroQuickJS的開(kāi)源項(xiàng)目。
這也是個(gè)JavaScript引擎,不過(guò)面向的是嵌入式設(shè)備。
我去項(xiàng)目主頁(yè)看了一下,好家伙,MicroQuickJS引擎運(yùn)行時(shí)僅需10K的內(nèi)存就可以編譯和運(yùn)行JavaScript程序,在這么小的空間下,運(yùn)行速度還接近QuickJS (這也是Bellard寫(xiě)的另外一個(gè)輕量級(jí)的JS引擎)。
才10K! 想想Node.js,想想Chrome V8,再想想Electron,這種極致的優(yōu)化能力實(shí)在是可怕。
怪不得Redis之父antirez說(shuō):如果這東西2010年就出現(xiàn)了,Redis的腳本語(yǔ)言就不會(huì)是Lua,而是JavaScript!
![]()
為什么 MicroQuickJS 可以這么小?
因?yàn)樗皇窃凇耙浦?JavaScript”,而是在“重新定義 JavaScript 在嵌入式設(shè)備上該是什么樣子”。
1. 只支持 ES5 的一個(gè)“精簡(jiǎn)版”
MicroQuickJS 支持的不是我們熟悉的那個(gè)“什么都能寫(xiě)”的 JavaScript,而是一個(gè)被刻意約束過(guò)的版本。
舉幾個(gè)例子你就能理解它的取舍邏輯:
- 只支持 strict mode,不再兼容歷史包袱,行為更簡(jiǎn)單、更可預(yù)測(cè),也更容易優(yōu)化。
- 數(shù)組不允許有“空洞”也就是說(shuō),不存在 arr[100] = 1,前面 99 個(gè)元素卻不存在的情況。這樣數(shù)組就可以用更緊湊的方式存儲(chǔ),而不是像散彈槍一樣到處打洞。
- 不支持直接 eval,eval 會(huì)讓代碼在運(yùn)行時(shí)突然“變身”,對(duì)內(nèi)存管理和優(yōu)化來(lái)說(shuō)是噩夢(mèng)。直接砍掉,整個(gè)引擎都清爽了。
- 日期只支持 Date.now(),不搞復(fù)雜的時(shí)區(qū)、格式化、歷史包袱,只提供“當(dāng)前時(shí)間戳”這個(gè)嵌入式最常用的功能。
- 字符串大小寫(xiě)轉(zhuǎn)換只支持 ASCII, 不支持完整 Unicode 的大小寫(xiě)映射,換來(lái)的是代碼量和內(nèi)存占用的大幅下降。
這些限制看起來(lái)有點(diǎn)“怪”,但你會(huì)發(fā)現(xiàn)它們都有一個(gè)共同目標(biāo): 確定、簡(jiǎn)單、省內(nèi)存。
2. 垃圾回收:不聰明,但非常狠
在內(nèi)存只有幾十 KB 的環(huán)境里,內(nèi)存碎片比“內(nèi)存不夠”更致命。
MicroQuickJS 的垃圾回收策略非常直接:追蹤式+壓縮式GC。
第一層:追蹤式 GC
它從一組“根對(duì)象”開(kāi)始,把所有還能被訪問(wèn)到的對(duì)象標(biāo)記出來(lái),剩下的一次性全清。
不需要在每個(gè)對(duì)象上維護(hù)引用計(jì)數(shù),不用擔(dān)心循環(huán)引用。
每個(gè)對(duì)象可以做得非常小,只需要幾個(gè) bit 的標(biāo)記信息
第二層:壓縮 GC
更狠的是:活下來(lái)的對(duì)象也不會(huì)原地不動(dòng)。在回收過(guò)程中,它會(huì)把所有存活對(duì)象重新排列、擠到一塊連續(xù)的內(nèi)存區(qū)域里。
內(nèi)存不再被切成一地碎片,后續(xù)分配變得非常簡(jiǎn)單,對(duì)小內(nèi)存設(shè)備極其友好
MicroQuickJS 完全不用系統(tǒng)的 malloc,而是自己實(shí)現(xiàn)了一套內(nèi)存分配器,這在嵌入式世界里非常重要,因?yàn)槟阌肋h(yuǎn)不知道系統(tǒng)自帶的分配器會(huì)偷偷浪費(fèi)多少內(nèi)存。
3. 用“變態(tài)”的方式表示 JS 的值和對(duì)象
這里是 Bellard 真正“炫技”的地方。
在 MicroQuickJS 里,一個(gè)值(數(shù)字、字符串、對(duì)象、函數(shù)等)統(tǒng)統(tǒng)只有一個(gè) CPU 字長(zhǎng)。
在 32 位系統(tǒng)上,就是 32 位,這意味著:所有值都能直接放進(jìn)寄存器,傳參、賦值、判斷都極其簡(jiǎn)單,內(nèi)存布局非常規(guī)整。
對(duì)象被壓縮到了極限,一個(gè) JavaScript 對(duì)象,最少只占 3 個(gè) CPU 字,在 32 位系統(tǒng)上就是 12 字節(jié),這已經(jīng)是能做到的極限了,只夠存對(duì)象的基本類型信息和指向?qū)傩员淼闹羔槨?/p>
屬性本身也不便宜,每個(gè)屬性至少 3 個(gè) CPU 字,所以“隨便給對(duì)象亂加屬性”在嵌入式里是很奢侈的事。這也解釋了為什么語(yǔ)言層面要對(duì)動(dòng)態(tài)性做那么多限制。
字符串也不走尋常路,內(nèi)部存儲(chǔ)用的是 UTF-8(更省空間),對(duì)外仍然表現(xiàn)為 JavaScript 熟悉的 UTF-16 語(yǔ)義,也就是說(shuō),存的時(shí)候省,語(yǔ)義上不破壞 JS 的規(guī)則。
4. 標(biāo)準(zhǔn)庫(kù)直接“焊死”在 ROM 里
在很多 JS 引擎中,啟動(dòng)時(shí)要?jiǎng)?chuàng)建 Object、Array、Math 等一大堆對(duì)象,這些對(duì)象會(huì)常駐內(nèi)存,占用 RAM。
MicroQuickJS 直接換了個(gè)思路: 編譯時(shí)就把這些標(biāo)準(zhǔn)庫(kù)對(duì)象生成好,以只讀數(shù)據(jù)的形式,固化進(jìn)程序鏡像,放在 ROM 里。
運(yùn)行時(shí)不需要再創(chuàng)建,只要引用即可,啟動(dòng)極快,RAM 占用極低。
總之,在嵌入式世界里,JavaScript 不再是“越全越好”,而是“剛剛好,能用就行”。
杰夫·阿特伍德(Jeff Atwood)說(shuō)過(guò),“任何可以用 JavaScript 編寫(xiě)的應(yīng)用程序,最終都會(huì)用 JavaScript 編寫(xiě)”。
![]()
這句話現(xiàn)在也適用于嵌入式系統(tǒng)了!
也許在不就以后,我們就能在傳感器、智能家居設(shè)備和可穿戴設(shè)備上看到JavaScript。
回到作者Bellard,他為人非常低調(diào),不拋頭露面,不寫(xiě)文章,不寫(xiě)書(shū)。
在互聯(lián)網(wǎng)上幾乎找不到對(duì)他直接的,深度采訪,只能找到他的一些只言片語(yǔ),例如:“我經(jīng)常會(huì)厭倦一直做同樣的事情,所以我會(huì)時(shí)不時(shí)地改變一下方向。”
由于他在如此多的領(lǐng)域,做出了常人根本無(wú)法企及的,不可思議的成就,有人甚至懷疑他就不是一個(gè)特定的人,而是一群人以這個(gè)id來(lái)發(fā)表軟件。
我想Bellard之所以看起來(lái)像“一群人”,并不是因?yàn)樗徽鎸?shí),而是因?yàn)槲覀冊(cè)缫蚜?xí)慣了工業(yè)化軟件生產(chǎn),卻突然遇到了一個(gè)仍然生活在“個(gè)人英雄時(shí)代”的程序員。
在今天這個(gè)時(shí)代,大多數(shù)重要軟件都需要龐大的團(tuán)隊(duì)、路線圖、測(cè)試、運(yùn)營(yíng);而 Bellard 的作品,總是像從真空中掉下來(lái)一樣:沒(méi)有預(yù)熱、沒(méi)有宏大宣言,代碼一放出來(lái),世界就不得不承認(rèn):規(guī)則被改寫(xiě)了。
這樣的人實(shí)在是太罕見(jiàn),實(shí)在是太神奇了!
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.