由Google開發的開源JavaScript引擎V8,將會在V8 11.2版本加入WebAssembly尾呼叫(Tail Calls)支援,避免遞迴呼叫消耗大量記憶體導致堆疊溢出,進一步提高遞迴函式執行效率。

尾呼叫是一種程式開發技巧,主要在函式程式語言中使用,藉此提高遞迴函式的效率,尾呼叫是指在函式最後一個操作呼叫另一個函式,但在呼叫完成之後不做任何額外的操作。而尾呼叫最佳化則是一種程式編譯器或是直譯器中的功能,可以避免尾呼叫導致額外的堆疊框。

由於每次函式呼叫時,編譯器便會創建一個稱為堆疊框(Stack Frame)的資料結構,來儲存區域變數和回傳位址,在遞迴中,這可能會導致大量堆疊框累積,最終消耗大量記憶體導致堆疊溢出,而編譯器可以透過丟棄堆疊框,以跳轉替換呼叫來最佳化呼叫。

一般遞迴函式呼叫會消耗O(n)的堆疊空間,而採用尾呼叫最佳化後,可以將遞迴函式簡化僅使用O(1)堆疊空間。也就是說,原本在計算過程,堆疊空間的需求會與問題規模成正比,當鏈結串列(Linked list)中的每個元素都要在呼叫堆疊上增加一個新的資料框,因此在列表太長時便會溢出堆疊,透過跳轉代替呼叫,便能夠使消耗的堆疊空間與問題規模無關。Google解釋,這種最佳化對函式程式語言很重要,因為函式語言嚴重仰賴遞迴函式。

但因爲偵測尾部位置的呼叫並非引擎的責任,而是由上游的工具鏈完成,因此V8的最佳化編譯器TurboFan的工作,便是根據呼叫類型和目標函式宣告,發出適當的指令序列。同時,V8中的WebAssembly基準編譯器(Baseline Compiler)Liftoff也支援尾呼叫,以避免基準程式碼耗盡堆疊空間,但是在這一層並沒有尾呼叫最佳化,會以一般呼叫運作方式處理。

熱門新聞

Advertisement