演示地址: PIB: PHP in Browser https://oraoto.github.io/pib/ , 你可以在上面运行 PHP 代码, 然后通过复制地址栏分享代码.
项目地址: https://github.com/oraoto/pib
某天晚上, 在看 Emscripten 的文档, 发现 Emscripten 有 emconfigure 和 emmake, 可以直接用 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 的新特性:
object 类型
抽象方法重写
可空类型
Void 函数
数组解构
类常量可见性
库函数方面支持比较少, 默认只编译了 date,pcre,bcmath,ctype,JSON,Reflection,SPL,tokenizer,standard,Core 这些扩展.
实现原理
原理并不复杂, 就是用 Emscripten 把 PHP 解释器编译到 webAssembly, 然后通过 JavaScript 调用 Zend 的 API.
为了能让 PHP 解释器编译成功, 需要对代码做少量修改, 主要是文件系统相关的两处代码, 我只直接注释掉或者 return 跳过代码.
对比现有方案
http://3v4l.org 这种在服务端执行代码然后返回结果到前端的方案已经很成熟, 在运行和分享 PHP 代码方面, PIB 的优势就是省去了我部署服务器的钱 (文件都在 GitHub pages).
也有其他的在浏览器直接运行 PHP 的方案:
https://github.com/zhikiri/php2wasm : 直接把 PHP 代码编译成 wasm, 现在还不成熟
https://github.com/juokaz/pyhp.js : 用 Pyton 实现 PHP 解释器 (PyHP, 据作者说性能比 PHP7 好), 然后再把这个解释器编译到 JS, 支持的特性有限, 作者已经弃坑
而 PIB 已经支持了大部分 PHP 语言特性, 不过性能和稳定性仍需提高.
未来
一开始设想是用 PHP 进行前端开发的, 但是实现不容易, 所以先做成这个样子了.
如果要让 PHP 代码操作浏览器的 DOM, 必须写 PHP 扩展, 使用 Emscripten 的 API 去调用 JavaScript, 这还是可以做的.
而 JavaScript 很多接口都是需要回调的, Emscripten 也是可以做到, 但是只是回调到 C/C++, 如果要回调到 PHP, 就要自己实现协程方案, 这我还做不了.
目前可以完善和尝试的:
语法检查
错误信息显示
减少代码体积
处理内存泄漏
如果你有什么有趣的想法, 也不妨提个 issue 或者评论一下.
来源: https://juejin.im/entry/5bbefc93e51d450e3e16e782