PHP扩展——C扩展实现滚动记录日志

前言

万事开头难,没错就是这样!!php

在没有真正开发PHP扩展以前,一直以为PHP扩展开发对我来讲是一个很遥远的事情,虽然本身有些C\C++基础,可是看PHP源码的时候仍是很吃力,如今看来主要仍是没有下决心搞这个,此次终于下决心搞一个php扩展类库,搞了一个周末,终于把以前的一个写日志的类库封装为php扩展的形式了,这也算是开发PHP扩展入门了,这里跟你们分享分享,这个是源代码:一个单例模式的记录日志的PHP扩展html

开发

我开发的是一个PHP扩展的形式进行日志记录,功能和前几天的PHP滚动日志基本一致,也是单例模式运行。git

记录下开发中要注意的几点:github

这里只是不多一部分,具体的能够看个人源代码,我以为最好的学习方式就是看源码了,遇到不会的不懂得本身去查,记忆更深入.centos

了解zval结构,zval是PHP内核中定义的数据结构
//定义在Zend/zend_types.h:55 和 Zend/zend.h:322行
typedef struct _zval_struct zval;
struct _zval_struct {
    /* Variable information */
    zvalue_value value;     /* value */
    zend_uint refcount;
    zend_uchar type;    /* active type */
    zend_uchar is_ref;
};
typedef union _zvalue_value {
    long lval;                  /* long value */
    double dval;                /* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;              /* hash table value */
    zend_object_value obj;
} zvalue_value;

//其中的zval.type表示变量的类型,基本类型有下面几种,定义在Zend/zend.h:583中
#define IS_NULL     0
#define IS_LONG     1
#define IS_DOUBLE   2
#define IS_BOOL     3
#define IS_ARRAY    4
#define IS_OBJECT   5
#define IS_STRING   6

//部分经常使用的zval相关函数或者宏,定义在Zend/zend_operators.h:441行
Z_LVAL_P(zval_p)    //获取zval_p指针所指向的zval结构的值,值得类型为LONG
Z_STRVAL_P(zval_p)
如何传参给函数
PHP扩展中接受参数的时候经过函数zend_parse_parameters,相似下面的形式进行传参:
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &msg, &msg_len);
第二个参数是要传入参数类型的列表,有下面规范

从PHP5.3开始, zend_parse_paramters_函数新增了以下几个新的类型描述符:
f - function or array containing php method call info (returned as zend_fcall_info and zend_fcall_info_cache)
H - array or HASH_OF(object) (returned as HashTable)
L - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (long)
Z - the actual zval (zval**)
开发面类库的时候经常使用的一些函数
zend_declare_property_null(mylogs_ce, ZEND_STRL("level"), ZEND_ACC_PRIVATE TSRMLS_CC);  
//相似上面的函数是类进行初始化的时候设置变量
zend_declare_class_constant_long(mylogs_ce, ZEND_STRL("LOG_DEBUG"), 0 TSRMLS_CC);
//相似上面的函数是类型进行初始化的时候设置常量
zend_read_property(mylogs_ce, instance, ZEND_STRL("level"), 0 TSRMLS_CC);
//上面的是从实例instance中读取变量的值
zend_hash_find(&ce->constants_table, ZEND_STRS("LOG_DEBUG"), (void **)&_level);
//上面的是从mylogs_ce这个类中读取常量
zend_update_property_long(mylogs_ce, instance, ZEND_STRL("level"), level TSRMLS_CC);
//上面的是从instance中读取变量level
注意
  1. 注意内存的释放,防止内存泄漏,我在开发完成以后,发现存在内存泄漏状况,能够利用valgrind查看内存泄漏状况,对再也不须要的内存即便进行释放,否则有可能在大量循环处理的时候出现内存占用过多,从而致使报错。
  2. 还有就是多看看例子,鸟哥的YAF源码能够多参考参考,这个帮了我不少,学习的初期就是“照猫画虎”。

看看效果

开发完成以后,写了个脚本试了下,循环输出日志10w次(准确的说是30w,debug、msg、err各10w次),下面是环境和结果
环境:数据结构

centos虚拟机,64位
内存 1G
CPU i5-2410M @ 2.30GHz #这个获取到的是我电脑的
次数 PHP代码 PHP扩展
第一次 8.83s 6.13s
第二次 8.60s 6.14s
平均 8.72s 6.14s

能够看到使用PHP扩展的方式速度能够提高原来的1/4左右,哈哈,还不错,个人代码可能还有很大的优化空间,加油努力~~函数

我将全部的代码放在了github上:学习

一个单例模式的记录日志的PHP扩展优化

参考文章

用C/C++扩展你的PHP —— Laruenceui

深刻PHP变量存储结构 —— 文大侠

5/24/2015 3:10:45 PM

本文版权归做者iforever(luluyrt@163.com)全部,未经做者本人赞成禁止任何形式的转载,转载文章以后必须在文章页面明显位置给出做者和原文链接,不然保留追究法律责任的权利。

相关文章
相关标签/搜索