php8引入jit後會發生什麼?

da_house發表於2020-11-30

連結:www.zhihu.com/question/319093848/a...

很多人可能對JIT有很深的誤解,覺得引入JIT之後效能就能提高10倍跟V8平起平坐了,事實上不是這樣的。

JIT技術的水很深,動態語言的JIT尤其困難,V8的誕生幾乎可以說是一個技術奇蹟。以PHP社群的技術水平,我謹慎地不看好他們解決這個問題的能力,畢竟Facebook的HHVM也沒有完全解決,最後是靠Hacklang補全PHP的語法功能之後才基本圓滿解決的。

動態語言的JIT本質要解決的問題之中,生成彙編只是一小部分,對於弱型別和動態型別語言來說,優化記憶體佈局也是重點。例如,對於JavaScript和Python來說,以前物件內部是一個HashMap,這種資料結構的訪問效率比較低,導致訪問物件的每個屬性都很慢,在JIT之後會將它優化成類似C++的平鋪式的佈局,將屬性的值按順序放在特定的位置上,這就帶來一些新的要求:

1. 沒有型別標註的情況下,JIT只能猜測型別而無法肯定,那麼使用優化的型別佈局之前需要進行額外的檢測,判斷是否的確為預想的型別

2. 屬性的型別也需要進一步推測,使用時也需要檢驗

3. JavaScript、Python乃至PHP都支援在物件建立之後為它新增新的屬性。之前符合推測的型別後來新增或者刪除了屬性,要怎麼處理?

除此之外,呼叫函式時候如何優化呼叫開銷也是一個重點,本質上跟優化物件的記憶體佈局是類似的,可以將傳入引數看成是構建一個有多個屬性的物件,每個屬性的型別不同。區域性變數也需要有選擇性地優化到暫存器、棧和堆當中。

PHP在這裡的優勢是支援型別標註,缺點是所有Hacklang裡面修改掉的部分:

1. 不支援泛型,尤其是array型別不支援泛型。將一個變數型別標註為array幾乎沒有任何幫助,PHP中的array可以是順序表也可以是hashmap,還可以混著,value的型別也不確定,這些都對型別優化有很高要求。Hacklang就推薦廢掉array改用vector等幾個確定型別且支援泛型的資料結構。

2. reference這個功能,這個功能非常容易成為記憶體佈局優化的障礙,也會阻礙JIT生成高效程式碼,尤其是陣列中可以儲存reference這件事,JIT編譯器完全無法從字面上判斷某條對array元素賦值的語句是否會影響環境中的其它變數的值。這也是為什麼Hacklang直接刪掉了這個功能。

3. 其他參考Hacklang的變更

之前版本(PHP7)摳直譯器實現帶來的效能優化也會是一個阻礙,JIT的時候這些都得放棄掉,因為記憶體佈局不一樣了,這樣可能導致最初的時候許多應用JIT反而變慢。

所以,PHP8如果解決不了這些問題,最大的可能是許多microbenchmark速度大幅上升,但整體應用效能持平,自娛自樂

對於cpu密集會有幫助,對於io密集幫助不大

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章