面试官:列举几种PHP拓展的实现手段及其性能比较?

 3547

关于 PHP 扩展的几种实现手段

1.php 原生扩展开发 c 语言,注:【ext_skel.php】脚本创建

2.zephir

3.php-cpp

4.php-x

5.cgo

封装 zendapi 模式

CGO 嵌套 C 和 GO 代码,用 GO 去编译了 php 扩展骨架和 GO 的具体实现

等。。。不限上面几种方式。

围绕【zephir,cgo,PHP 开启 JIT】4 种模式下,通过斐波那契数列计算性能,来查看运行效果。


zephir 代码生成扩展

  1. //Main 类
  2. final class Zimuge 
  3. {
  4.   public static function calcFibonacci(int i)
  5.   {
  6.     if (< 2) {
  7.         return i;
  8.     }
  9.   return self::calcFibonacci(- 1) + self::calcFibonacci(- 2);
  10.   }
  11. }

编译安装

  1. zephir build


cgo 代码生成扩展

  1. package main
  2. /*
  3. #ifdef HAVE_CONFIG_H
  4. #include "config.h"
  5. #endif
  6. #include "php.h"
  7. #include "php_ini.h"
  8. #include "ext/standard/info.h"
  9. static int le_go2php;
  10. PHP_MINIT_FUNCTION(go2php)
  11. {
  12.     return SUCCESS;
  13. }
  14. PHP_MSHUTDOWN_FUNCTION(go2php)
  15. {
  16.     return SUCCESS;
  17. }
  18. PHP_RINIT_FUNCTION(go2php)
  19. {
  20.     return SUCCESS;
  21. }
  22. PHP_RSHUTDOWN_FUNCTION(go2php)
  23. {
  24.     return SUCCESS;
  25. }
  26. PHP_MINFO_FUNCTION(go2php)
  27. {
  28.     php_info_print_table_start();
  29.     php_info_print_table_header(2, "go2php support", "enabled");
  30.     php_info_print_table_end();
  31. }
  32. PHP_FUNCTION(go2php_print)
  33. {
  34.     zend_long a,b;
  35.     ZEND_PARSE_PARAMETERS_START(1, 1)
  36.         Z_PARAM_LONG(a)
  37.     ZEND_PARSE_PARAMETERS_END();
  38.     b = calcFib(a);
  39.     RETURN_LONG(b);
  40. }
  41. ZEND_BEGIN_ARG_INFO(null, 0)
  42. ZEND_END_ARG_INFO()
  43. const zend_function_entry go2php_functions[] = {
  44.     PHP_FE(go2php_print, null)
  45.     PHP_FE_END
  46. };
  47. zend_module_entry go2php_module_entry = {
  48.     STANDARD_MODULE_HEADER,
  49.     "go2php",
  50.     go2php_functions,
  51.     PHP_MINIT(go2php),
  52.     PHP_MSHUTDOWN(go2php),
  53.     PHP_RINIT(go2php),
  54.     PHP_RSHUTDOWN(go2php),
  55.     PHP_MINFO(go2php),
  56.     "0.1.0",
  57.     STANDARD_MODULE_PROPERTIES
  58. };
  59. #ifdef COMPILE_DL_GO2PHP
  60. ZEND_GET_MODULE(go2php)
  61. #endif
  62. */
  63. import "C"
  64. func main() {}
  1. package main
  2. import "C"
  3. //export calcFib
  4. func calcFib(int) int {
  5.     if i < 2 {
  6.         return i
  7.     }
  8.     return calcFib(i-1)+calcFib(i-2)
  9. }


编译&链接

  1. CGO_CFLAGS="-g \
  2. -I`/root/download/php8/bin/php-config --include-dir` \
  3. -I`/root/download/php8/bin/php-config --include-dir`/main \
  4. -I`/root/download/php8/bin/php-config --include-dir`/TSRM \
  5. -I`/root/download/php8/bin/php-config --include-dir`/Zend \
  6. -I`/root/download/php8/bin/php-config --include-dir`/ext \
  7. -I`/root/download/php8/bin/php-config --include-dir`/ext/date/lib \
  8. -DHAVE_CONFIG_H" CGO_LDFLAGS="-Wl,--export-dynamic -Wl,--unresolved-symbols=ignore-all" go build -p 1 -gcflags "-l" -buildmode=c-shared -o go2php.so


测试用 php 脚本代码

  1. <?php
  2. const COUNT = 30;
  3. function calcFibonacci(int $i): int {
  4.     if ($i < 2) {
  5.         return $i;
  6.     }
  7.     return calcFibonacci($i - 1) + calcFibonacci($i - 2);
  8. }
  9. // CGO 速度
  10. $startTime = microtime(true);
  11. for($i = 1; $i <= COUNT; $i++) {
  12.     if($i != COUNT) {
  13.         go2php_print($i);
  14.     }else {
  15.         echo go2php_print($i)."\n";
  16.     }
  17. }
  18. $time = microtime(true) - $startTime;
  19. echo "CGO: {$time} 秒\n";
  20. //zephir 速度
  21. $startTime = microtime(true);
  22. for($i = 1; $i <= COUNT; $i++) {
  23.     if($i != COUNT) {
  24.         Lsz\Zimuge::calcFibonacci($i);
  25.     }else {
  26.         echo Lsz\Zimuge::calcFibonacci($i)."\n";
  27.     }
  28. }
  29. $time = microtime(true) - $startTime;
  30. echo "zephir: {$time} 秒\n";
  31. // PHP JIT 速度
  32. $startTime = microtime(true);
  33. for($i = 1; $i <= COUNT; $i++) {
  34.     if($i != COUNT) {
  35.         calcFibonacci($i);
  36.     }else {
  37.         echo calcFibonacci($i)."\n";
  38.     }
  39. }
  40. $time = microtime(true) - $startTime;
  41. echo "PHP: {$time} 秒\n";

不使用 PHP JIT 的情况下测试

  1. php test.php
  2. ->执行结果取一个平均
  3. 832040
  4. CGO: 0.059875011444092 
  5. 832040
  6. zephir: 8.5679790973663 
  7. 832040
  8. PHP: 0.75995492935181 

使用 PHP JIT 的情况下测试

  1. php -dopcache.enable_cli=1 -dopcache.jit_buffer_size=100M test.php 
  2. ->执行结果取一个平均
  3. 832040
  4. CGO: 0.046900987625122 
  5. 832040
  6. zephir: 5.5882248878479 
  7. 832040
  8. PHP: 0.10621190071106 

cgo 和 zephir 编译后的 so文件,通过php.ini 引入进来

执行测试脚本需要保证so正确读取进来。

命令 php -m 或者 php --ri xx.so 进行确认。

  1. [PHP Modules]
  2. Core
  3. ctype
  4. curl
  5. date
  6. dom
  7. FFI
  8. fileinfo
  9. filter
  10. gd
  11. go2php
  12. hash
  13. iconv
  14. json
  15. libxml
  16. lsz
  17. mbstring
  18. mysqlnd
  19. openssl
  20. pcre
  21. PDO
  22. pdo_mysql
  23. pdo_sqlite
  24. Phar
  25. posix
  26. redis
  27. Reflection
  28. session
  29. SimpleXML
  30. SPL
  31. sqlite3
  32. standard
  33. swoole
  34. tokenizer
  35. xml
  36. xmlreader
  37. xmlwriter
  38. yaf
  39. Zend OPcache
  40. zephir_parser
  41. zimuge
  42. [Zend Modules]
  43. Zend OPcache

使用PHP版本

  1. php -v
  2. PHP 8.1.3 (cli) (built: Feb 27 2022 19:40:08) (NTS)
  3. Copyright (c) The PHP Group
  4. Zend Engine v4.1.3, Copyright (c) Zend Technologies
  5.     with Zend OPcache v8.1.3, Copyright (c), by Zend Technologies

结论:

JIT 能提高 php 的性能。

想学习 go 又不想放弃 php 可以用玩下 CGO。

zephir 虽然计算性能不太好,但是写 PHP 扩展实现起来比较简单。


TAG标签:
本文网址:https://www.zztuku.com/index.php/detail-11396.html
站长图库 - 面试官:列举几种PHP拓展的实现手段及其性能比较?
申明:本文转载于《learnku》,如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐