通過 WebAssembly 在瀏覽器執行 PHP

Oraoto發表於2018-05-30

file

演示地址:PIB: PHP in Browser,你可以在上面執行PHP程式碼,然後通過複製位址列分享程式碼。

專案地址:oraoto/pib

某天晚上,在看Emscripten的文件,發現Emscripten有emconfigureemmake,可以直接用Emscripten替換編譯器實現專案移植,靈光一現就有了這個專案。

效能測試

Firefox和Edge載入更快,使用者體驗要比Chrome好一點 :)

首先娛樂測試一下,改自eechen的測試,10萬的陣列填充和字串拼接:

<?php

$start = microtime(true);

$arr = [];

for ($i = 0; $i < 100000; $i++) {
    $time = microtime(true);
    $arr[$i . '_' . $time] = $time;
}

echo (microtime(true) - $start) . PHP_EOL;

點我直接跑一下

我的電腦CPU是i5-6400,Chrome 66耗時0.35秒,Firefox耗時0.25秒,而原生PHP 7.2只需0.048秒,也就是說效能大約是原生PHP 7.2的1/7左右。

跑PHP原始碼自帶的Zend/bench.php

simple             0.288
simplecall         0.088
simpleucall        0.226
simpleudcall       0.241
mandel             1.138
mandel2            1.251
ackermann(7)       0.221
ary(50000)         0.037
ary2(50000)        0.033
ary3(2000)         0.626
fibo(30)           0.855
hash1(50000)       0.067
hash2(500)         0.084
heapsort(20000)    0.264
matrix(20)         0.285
nestedloop(12)     0.444
sieve(30)          0.178
strcat(200000)     0.043
------------------------
Total              6.369

而原生PHP 7.2只要0.591秒,差了近11倍。

功能測試

因為是直接編譯PHP解析器,所以語言層面的大部分功能都是支援的,目前已知不支援的只有Generator(已支援)。

可以試試PHP7的新特性:

庫函式方面支援比較少,預設只編譯了datepcrebcmathctypejsonReflectionSPLtokenizerstandardCore這些擴充套件。

實現原理

原理並不複雜,就是用Emscripten把PHP直譯器編譯到WebAssembly,然後通過JavaScript呼叫Zend的API。

為了能讓PHP直譯器編譯成功,需要對程式碼做少量修改,主要是檔案系統相關的兩處程式碼,我只直接註釋掉或者return跳過程式碼。

對比現有方案

3v4l這種在服務端執行程式碼然後返回結果到前端的方案已經很成熟,在執行和分享PHP程式碼方面,PIB的優勢就是省去了我部署伺服器的錢(檔案都在Github pages)。

也有其他的在瀏覽器直接執行PHP的方案:

  • php2wasm:直接把PHP程式碼編譯成wasm,現在還不成熟
  • pyhp.js:用Pyton實現PHP直譯器(PyHP,據作者說效能比PHP7好),然後再把這個直譯器編譯到JS,支援的特性有限,作者已經棄坑

而PIB已經支援了大部分PHP語言特性,不過效能和穩定性仍需提高。

未來

一開始設想是用PHP進行前端開發的,但是實現不容易,所以先做成這個樣子了。

如果要讓PHP程式碼操作瀏覽器的DOM,必須寫PHP擴充套件,使用Emscripten的API去呼叫JavaScript,這還是可以做的。

而JavaScript很多介面都是需要回撥的,Emscripten也是可以做到,但是隻是回撥到C/C++,如果要回撥到PHP,就要自己實現協程方案,這我還做不了。

目前可以完善和嘗試的:

  1. 語法檢查
  2. 錯誤資訊顯示
  3. 減少程式碼體積
  4. 處理記憶體洩漏

如果你有什麼有趣的想法,也不妨提個issue或者評論一下。

2018.10.20:

  1. PHP升級到7.3 RC2
  2. Ace編輯器提供基本的語法檢查
  3. 通過LLVM LTO效能提高了1倍,檔案縮小到3.9M(gzip後1.1M)
  4. 記憶體洩漏再次出現(曾經的變通方案無效了)

相關文章