利用wasm的jit加速功能對程式碼進行加速
wasm程式碼的執行一共有三種模式。最早的有兩種:binaryen模式和wavm模式。最近還加了一種叫wabt的基於棧的bytecode模式。
binaryen模式是基於bytecode的直譯器的。而wavm模式是基於JIT的,速度可以達到執行native code的級別。但是wavm模式有一個致命的硬傷:JIT時編譯速度太慢。以編譯原始碼裡的eosio.system這個系統智慧合約為例,需要5秒左右的時間。這已經不是慢的問題的,而是在每個塊0.5秒的情況下,已經根本無法滿足需求了。另外,現在的wavm模式佔用的記憶體比較大,大得讓大部分的智慧合約的釋出者無法承受,所以,除非是後面wavm模式有比較大的優化,要不然,在目前情況下,直接給wavm模式的大量使用宣判了死刑。
那說了這麼多,wavm模式還有什麼用呢?
其中一個作用是在replay的時候加快replay的速度。但是這會佔用大量額外的記憶體。另外,鑑於JIT模式下的潛在的安全問題比較多,所以在生產環境下還是不建議使用。
還有一個作用是給特權級別的合約進行加速。最常用的就是eosio.token和eosio.system這兩個合約。
另外,wavm JIT模式雖然不能被大量使用,但是可以把它定義為一種稀缺資源。像短帳戶名稱一樣通過競價的方式來獲取。另一種更為簡單的的方式就是就是讓智慧合約的賬戶來承擔wavm JIT模式下的額外記憶體費用。
說了wavm JIT加速的應用場景,接下來就是實現的問題了。由於wavm JIT加速模式的載入時間比較長,所以必須採用非同步載入的模式。在載入過程中,合約可以執行在wabt這種更快的直譯器的模式之下。
但是上面的方法還是要解決一個問題。就是wasm的程式碼目前只支援單執行緒執行,另外,由於wasm的設計問題,並不支援wavm和wabt兩種模式的共存。也就是說,在程式的初始化的過程中必須指定一種執行模式,wabt模式或者wavm模式。但是在程式跑起來後,就只能以wabt模式或者wavm模式運行了,否則會因為記憶體衝突導致程式的崩潰。這個問題也應該是後面Eos的要面對的一個問題。PyEos的解決辦法是採用將相同的程式碼編譯成兩個動態庫,這兩個動態庫是不會共享記憶體的,從而解決了wavm模式和wabt模式下記憶體衝突導致程式崩潰的問題。
實現的程式碼在如下的路徑:libraries/vm/vm_wasm,感興趣的可以找到程式碼研究下,這裡就不展開了。