用C编写你自己的php扩展

本文链接:http://blog.csdn.net/ddjohn/article/details/42317675

本文参考:http://blog.csdn.net/taft/article/details/596291

如果你没写过php扩展,又是追求性能的极客,那么这篇文章肯定适合你:

假如你有这样一个php程序

function self_concat($string, $n){
    $result = "";
    for($i = 0; $i < $n; $i++){
        $result .= $string;
    }
    return $result;
}
$str = self_concat('fire',10);

如果传入的第二个参数N很大,程序的性能如何?我在自己的机器上测试下如果 n=10000000的时候耗时0.6s左右 如果用C写这个php function然后php直接调用,会快么?那就开始写这样一个简单的扩展吧,采用静态编译成.so的方式来加载,我用最快最简明的方式说明。

1.首先你需要有php的源码目录 cd到其ext目录下执行:

./ext_skel --extname=luckyext --proto=luckyext.def

这条命令会自动生成一个名叫luckyext的目录 里面有基本的扩展骨架文件,核心的文件只有三个 congif.m4用来做编译配置,luckyext.h定义都文件包括声明你的自定义函数,还有luckyext.c用来写C的函数源码,其他都是附加的骨架文件,暂时可以不用管。

2.在luckyext.c内编写你要的函数,记得在头文件内声明,不然编译的时候会报错

PHP_FUNCTION(self_concat_c)
 
{
 
char *str = NULL;
 
int argc = ZEND_NUM_ARGS();
 
int str_len;
 
long n;
 
char *result; /* Points to resulting string */
 
char *ptr; /* Points at the next location we want to copy to */
 
int result_length; /* Length of resulting string */
 
if (zend_parse_parameters(argc TSRMLS_CC, "sl", &str, &str_len, &n) == FAILURE)
 
return;
 
/* Calculate length of result */
 
result_length = (str_len * n);
 
/* Allocate memory for result */
 
result = (char *) emalloc(result_length + 1);
 
/* Point at the beginning of the result */
 
ptr = result;
 
while (n--) {
 
/* Copy str to the result */
 
memcpy(ptr, str, str_len);
 
/* Increment ptr to point at the next position we want to write to */
 
ptr += str_len;
 
}
 
/* Null terminate the result. Always null-terminate your strings
 
even if they are binary strings */
 
*ptr = '\0';
 
/* Return result to the scripting engine without duplicating it*/
 
RETURN_STRINGL(result, result_length, 0);
 
} 

3.编译扩展 关于php的环境配置就不说了

phpize
./configure
make&&make install

成功编译的话会在你的php指定的扩展目录中生成一个luckyext.so的文件

4.引入扩展重新加载php

vi /etc/php.ini
extension=luckyext.so
我是mac机,修改的时候请看自己机器的配置,修改完后保存重启fpm
killall php-fpm
php-fpm

5.测试

终端输入

php -m
出来的扩展中应该有luckyext了,至于它支持什么函数 可以用ext/luckyext目录内的luckyext.php脚本去运行看看 正常情况会输出它支持的函数self_concat_c()

6.性能对比 直接运行C写的php

<?php
self_concat_c('fire',10000000);

出来的结果耗时是惊人的,0.06秒,相差10倍!为什么呢,因为如果用php那套代码,每次往字符串塞字符的时候,php都需要做一个内存的动态分配,循环越多次,性能开销就越大,而C写的function直接就计算出最终需要分配多少内存了,所以快就快在这里,是不是很有趣~哈哈,至少我觉得很刺激!

本文的C例子属参考前辈翻译的文件,以后要多修修C的功底才行了,后面我会研究更多C的知识,加油!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。