機器只能理解機器語言,而PHP作為解釋型指令碼到底是如何被機器執行的呢?
實際上PHP在執行過程中,分為 詞法分析、文法分析、編譯PHP指令碼為opcode,最後Zend引擎會執行這些opcode。
在上述執行過程中,經常被人提起的解釋型語言效能問題也就是因為每次執行指令碼,上述過程都會重複執行。因此,也就出現了APC, xcache, eAccelerator等緩衝opchode。
一、安裝VLD擴充(linux)
1、下載
地址:http://pecl.php.net/package/vld
2、解壓安裝
# tar zxvf vld-0.11.1.tgz# cd ./vld-0.11.1# /usr/local/php/bin/phpize # ./configure --with-php-config=/usr/local/php/bin/php-config --enable-vld# make && make install
這裡,為下載的是vld-0.11.1.tgz,並且我的PHP路徑為/usr/local/php
3、修改php.ini
extension=vld.so
4、重啟apache或php-fpm
二、通過簡單的例子,看看opcode
PHP代碼:
<?phpecho "hello world\n";$str = "strtest";$str2 = "jinyong";print strlen($str);echo strlen($str2);
opcode:
通過你能獲得哪些資訊呢?
行號、指令編號、指令碼開始標記、結束標記、ZEND VM指令、傳回值、ZEND VM指令對應的參數。
三、ZEND VM執行opcode
struct _zend_op { opcode_handler_t handler; // 執行該opcode時調用的處理函數 znode result; znode op1; znode op2; ulong extended_value; uint lineno; zend_uchar opcode; // opcode代碼};struct _zend_op_array {/* Common elements */zend_uchar type;char *function_name;zend_class_entry *scope;zend_uint fn_flags;union _zend_function *prototype;zend_uint num_args;zend_uint required_num_args;zend_arg_info *arg_info;zend_bool pass_rest_by_reference;unsigned char return_reference;/* END of common elements */zend_bool done_pass_two;zend_uint *refcount;zend_op *opcodes;zend_uint last, size;zend_compiled_variable *vars;int last_var, size_var;zend_uint T;zend_brk_cont_element *brk_cont_array;int last_brk_cont;int current_brk_cont;zend_try_catch_element *try_catch_array;int last_try_catch;/* static variables support */HashTable *static_variables;zend_op *start_op;int backpatch_count;zend_uint this_var;char *filename;zend_uint line_start;zend_uint line_end;char *doc_comment;zend_uint doc_comment_len;zend_uint early_binding; /* the linked list of delayed declarations */void *reserved[ZEND_MAX_RESERVED_RESOURCES];};ZEND_API void execute(zend_op_array *op_array TSRMLS_DC){ // ... 迴圈執行op_array中的opcode或者執行其他op_array中的opcode}
實際上我們編寫的PHP,最終解析成ZEND VM中的指令集,最終通過ZEND VM返回結果。
每一條指令,都可以找到對用的函數執行,例如ECHO指令對應zend_do_echo。更多的可以查看Zend/compile.h
更多指令參見:http://php.net/manual/en/internals2.opcodes.list.php,同時列出了每條指令的案例