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)全部,未經做者本人贊成禁止任何形式的轉載,轉載文章以後必須在文章頁面明顯位置給出做者和原文鏈接,不然保留追究法律責任的權利。

相關文章
相關標籤/搜索