作为我在Web领域的入门措辞,对PHP的感情犹如初恋一样平常美好。但伴随着近几年来大家对PHP各种调侃、讽刺,加上新措辞Go、Rust、Javascript等强势崛起。彷佛让“我是一名PHP程序员”变得底气很不敷。来源于Web、辉煌于Web、受限于Web,不得不说,这让脚本措辞PHP陷入了困境,由于Web已经不再是那个靠渲染网页的PC时期,虽然目前有Swoole这样精良的异步方案,但也很难让我对PHP提起足够的兴趣。
Rust作为近几年来逐步盛行的新兴措辞,凭借安全、高效、可靠,开始进入了人们的视野。周末,重拾起了PHP,想看看是否能够在PHP和Rust之间擦出一点点火花。当然,只是出于个人兴趣做的一些实验,这并不能为两个精良的措辞带来什么改变。但我想,至少能够让大家对PHP和Rust有更多的理解。
PHP7.4中的FFI
起初,PHP7.4中的新特性FFI引起我很大的兴趣,由于在很多措辞中已经拥有了这样的特性,例如:Python、NodeJS、Ruby等,PHP首次的引入,让我以为PHP团队正在朝着这方面进行努力。
我首先采取Rust编写了一个Fibonacci斐波那契数列,这里实现了一个大略的打算函数,我将他导出为动态链接库,以供PHP的FFI调用。
#[no_mangle]pub extern fn fib(n: i32) -> i32 { return match n { 1 | 2 => 1, n => fib(n - 1) + fib(n - 2) }}
编写完成后,我考试测验在PHP的FFI中进行调用,为了想比拟下性能,我同时编写了一个PHP的函数:
// 一个PHP的fib函数function fib($n) { if ($n === 1 || $n === 2) {return 1;} else {return fib($n-1) + fib($n-2);} }
接下来,我在PHP中调用他们,为了能够看出性能差异,我将调用1000000次:
// release模式$ffiRelease = FFI::cdef( \公众int32_t fib(int32_t n);\"大众, \公众r2p-fib/target/release/libr2pfib.$libExtension\公众);$time_start = microtime(true);for ($i=0; $i < 10000000; $i++) { $v = $ffiRelease->fib(12);}echo '[Rust]Release实行韶光:' . (microtime(true) - $time_start).PHP_EOL;
从测试结果来看,Rust的FFI结果是让人惊喜的。
PHP的打算耗时30秒以上,Rust仅仅用了6秒。
当我为此欣喜若狂的时候,我又考试测验了下PHP的FFI调用天生字符串,在PHP中是类似这样一个方法:
function text_generate($num) {$result = \"大众\"大众;$result .= str_repeat(\"大众na \公众,$num);$result .= \"大众Batman! \"大众;return $result;}
结果Rust由于在PHP的FFI中间字符串转换的损耗,性能并没有达到预想那样。
PHP扩展调用Rust动态库
由于第一个操作,让我想到了FFI在多次调用性能损耗是很大的,这时我想实现在PHP扩展中来调用Rust动态库。
同时为了比拟,我编写一个C的Fib函数进行比较。
我创建了一个名为rust的PHP扩展,完成了关于我们上面编写的Rust函数的调用。
ZEND_BEGIN_ARG_INFO(arginfo_rust_fib, 0)ZEND_ARG_INFO(0, number)ZEND_END_ARG_INFO()/ {{{ int rust_fib( [ int $var ] ) /PHP_FUNCTION(rust_fib){zend_long number = 0;zend_long result = 0;ZEND_PARSE_PARAMETERS_START(0, 1)Z_PARAM_OPTIONALZ_PARAM_LONG(number)ZEND_PARSE_PARAMETERS_END();if (number == 0) {RETURN_LONG(result);} else {result = fib(number);RETURN_LONG(result);}}/ }}}/
结果同样让我惊喜,没有了FFI,它确实提升了20%旁边的性能。但很明显,它的实现繁芜度更高了。
采取Rust编写PHP扩展
将PHP的Zend API构造导出,直接在Rust中实现PHP模块的编写。虽然自己没有足够的精力去做这样的考试测验,但我以为这是一个可行的方法。我想在未来的韶光内完成这样的考试测验。
总结
虽然影响PHP更好的发展的紧张成分并不是性能,只管本篇只是从性能提升入手对PHP进行了测试,但我以为,作为一个拥有如此弘大开拓群体的Web措辞,也是时候须要跟Go、Rust、Node这些新兴措辞学习了,建立并不局限于Web领域的新的生态体系,大胆的去做一些新的考试测验,让PHP不再是“天下第一措辞”。
本文完全测试代码及结果请参考:https://github.com/llgoer/php-ffi-rust/