PHP安装与使用VLD查看opcode代码【PHP安装第三方扩展的方法】
需要分析PHP代碼的性能,或者說實現同樣功能的代碼到底哪個更好呢?或者說想知道底層的實現可以使用VLD查看opcode
下載與安裝VLD
# wget http://pecl.php.net/get/vld-0.11.2.tgz
# tar zxvf vld-0.11.2.tgz
# cd ./vld-0.11.2
# /usr/local/php/bin/phpize????????????? 或者直接phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-vld
# make && make install
---------------------------------
編輯php.ini文
php.ini位置
#cd /usr/local/php/lib
增加
extension=
?
重啟Apache:
# /usr/local/apache2/bin/apachectl restart
---------------------------------?
查看phpinfo()信息
?
--------------------------------
至此,VLD就安裝完了。寫個簡單的test.php
$a='123';
echo $a;
?
?
# php -dvld.active=1 ./test.php
如果沒有設置php環境變量的話
#/usr/local/php/bin/php? -dvld.active=1? test.php
查看結果
?
如上為VLD輸出的PHP代碼生成的中間代碼的信息,說明如下:
- Branch analysis from position 這條信息多在分析數組時使用。
- Return found 是否返回,這個基本上有都有。
- filename 分析的文件名
- function name 函數名,針對每個函數VLD都會生成一段如上的獨立的信息,這里顯示當前函數的名稱
- number of ops 生成的操作數
- compiled vars 編譯期間的變量,這些變量是在PHP5后添加的,它是一個緩存優化。這樣的變量在PHP源碼中以IS_CV標記。
- op list 生成的中間代碼的變量列表
使用-dvld.active參數輸出的是VLD默認設置,如果想看更加詳細的內容。可以使用-dvld.verbosity參數。
?
#php -dvld.active=1 -dvld.verbosity=3 text.php
-dvld.verbosity=3是VLD在當前版本可以顯示的最詳細的信息.
如果我們只是想要看輸出的中間代碼,并不想執行這段PHP代碼,可以使用-dvld.execute=0來禁用代碼的執行
#php -dvld.active=1 -dvld.execute=0 text.php
?
VLD擴展的參數列表:
- -dvld.active 是否在執行PHP時激活VLD掛鉤,默認為0,表示禁用。可以使用-dvld.active=1啟用。
- -dvld.skip_prepend 是否跳過php.ini配置文件中auto_prepend_file指定的文件, 默認為0,即不跳過包含的文件,顯示這些包含的文件中的代碼所生成的中間代碼。此參數生效有一個前提條件:-dvld.execute=0
- -dvld.skip_append 是否跳過php.ini配置文件中auto_append_file指定的文件, 默認為0,即不跳過包含的文件,顯示這些包含的文件中的代碼所生成的中間代碼。此參數生效有一個前提條件:-dvld.execute=0
- -dvld.execute 是否執行這段PHP腳本,默認值為1,表示執行。可以使用-dvld.execute=0,表示只顯示中間代碼,不執行生成的中間代碼。
- -dvld.format 是否以自定義的格式顯示,默認為0,表示否。可以使用-dvld.format=1,表示以自己定義的格式顯示。這里自定義的格式輸出是以-dvld.col_sep指定的參數間隔
- -dvld.col_sep 在-dvld.format參數啟用時此函數才會有效,默認為 “\t”。
- -dvld.verbosity 是否顯示更詳細的信息,默認為1,其值可以為0,1,2,3 其實比0小的也可以,只是效果和0一樣,比如0.1之類,但是負數除外,負數和效果和3的效果一樣 比3大的值也是可以的,只是效果和3一樣。
- -dvld.save_dir 指定文件輸出的路徑,默認路徑為/tmp。
- -dvld.save_paths 控制是否輸出文件,默認為0,表示不輸出文件
- -dvld.dump_paths 控制輸出的內容,現在只有0和1兩種情況,默認為1,輸出內容
?
使用VLD比較代碼差異
代碼text1.php
$var = 111;
$str = "AAA " . $var . " BBB";
代碼text2.php
$var = 111;
$str = "AAA $var BBB";
從結果很清晰的看出第一段代碼比第二段代碼多了concat
第一個連接操作,將“test string begin ”和$var連接起來,得到“AAA 111”,然后再執行第二個連接操作,將上一個操作得到的結果“AAA 111”和” BBB”連接起來,并將結果存儲在另一個臨時變量,最后將第二個連接操作的結果賦值給$str。
連接操作對應的opcode為ZEND_CONCAT,對于所給的兩個操作數,其最終通過concat_function函數將兩個字符串連接起來,如果所給的變量的類型不是字符串,則會通過zend_make_printable_zval將其轉換成字符串。concat_function函數會根據兩個字符串的長度重新分配內存,并執行兩次拷貝操作,將兩個字符串拷貝到新的內存空間。這里針對兩個字符串相同的情況有一個特殊處理。
if (result==op1) { /* special case, perform operations on result */uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);Z_STRVAL_P(result) = erealloc(Z_STRVAL_P(result), res_len+1);memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2));Z_STRVAL_P(result)[res_len]=0;Z_STRLEN_P(result) = res_len;
} else {Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1);memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1));memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;Z_TYPE_P(result) = IS_STRING;
}
而直接在字符串中插入變量,其所有的操作都是添加操作,將字符串添加到返回值,將變量添加到返回值,
所有的結果返回都是在一個臨時變量中,如我們的示例,首先會將”AAA “添加到臨時變量,然后將臨時變量和$var變量添加到臨時變量,之后將臨時變量和” BBB”添加到臨時變量,最后將此此時變量賦值給$str。這里添加將字符串添加到臨時變量,其對應的opcode為ZEND_ADD_STRING,將變量添加到臨時變量,其對應的opcode為ZEND_ADD_VAR,雖然這兩個操作的opcode不同,但其最終調用都是add_string_to_string,他們所不同的調用此函數的第三個參數,一個是操作碼存儲的ZVAL變量,一個是通過變更列表獲取的ZVAL變量。
如果覺得需要看C語音級別的php源碼,可以參考:使用strace查看C語言級別的php源碼
如果你要查看memcpy可以去這個網站
http://linux.about.com/od/commands/l/blcmdl.htm
搜索結果在:http://linux.about.com/library/cmd/blcmdl3_memcpy.htm
========================
延伸閱讀參考:
http://www.phppan.com/2011/05/vld-extension/
PHP中的字符串連接操作
http://blog.csdn.net/phpkernel/article/details/5718519
http://www.laruence.com/2008/08/19/338.html
總結
以上是生活随笔為你收集整理的PHP安装与使用VLD查看opcode代码【PHP安装第三方扩展的方法】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php安装完成以后要复制php.ini文
- 下一篇: 求一个好听的冷饮名字!