国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > PHP > 正文

快速找出php中可能導致cpu飆升問題的代碼行

2024-05-04 21:49:49
字體:
來源:轉載
供稿:網友

cpu飆升占100%不但是與數據庫或硬盤的io輸入有關,但程序也是一個非常重要的地方了,今天小編找到一個代碼可以測試你的php引起cpu占100%問題的解決辦法,有興趣的朋友可進入參考.

用cpu接近100%時,你如何找到導致cpu飆升的原因?我的思路是,首先找到進程正在執行的代碼行,從而確定可能有問題的代碼段,然后,再仔細分析有問題的代碼段,從而找出原因.

如果你的程序使用的是c、c++編寫,那么你可以很容易的找到正在執行的代碼行,但是,程序是php編寫的,如何找到可能有問題的代碼行呢?這個問題就是本文要解決的問題.

背景知識:大家都知道php是一個解釋性語言,用戶編寫的php代碼會生成opcode,由解釋器引擎去解釋執行,在解釋執行過程中,有一個全局變量包含了執行過 程中用到的各種數據,它就是executor_globals,在源碼的Zend/zend_globals.h 文件中可以找到他的類型定義,代碼如下:

  1. struct _zend_executor_globals { 
  2.     zval **return_value_ptr_ptr; 
  3.     zval uninitialized_zval; 
  4.     zval *uninitialized_zval_ptr; 
  5.     zval error_zval; 
  6.     zval *error_zval_ptr; 
  7.     zend_ptr_stack arg_types_stack; 
  8.     /* symbol table cache */ 
  9.     HashTable *symtable_cache[SYMTABLE_CACHE_SIZE]; 
  10.     HashTable **symtable_cache_limit; 
  11.     HashTable **symtable_cache_ptr; 
  12.     zend_op **opline_ptr; 
  13.     HashTable *active_symbol_table; 
  14.     HashTable symbol_table;     /* main symbol table */ 
  15.     HashTable included_files;   /* files already included */ 
  16.     JMP_BUF *bailout; 
  17.     int error_reporting
  18.     int orig_error_reporting; 
  19.     int exit_status; 
  20.     zend_op_array *active_op_array; 
  21.     HashTable *function_table;  /* function symbol table */ 
  22.     HashTable *class_table;     /* class table */ 
  23.     HashTable *zend_constants;  /* constants table */ 
  24.     zend_class_entry *scope; 
  25.     zend_class_entry *called_scope; /* Scope of the calling class */ 
  26.     zval *This; 
  27.     long precision; 
  28.     int ticks_count; 
  29.     zend_bool in_execution; 
  30.     HashTable *in_autoload; 
  31.     zend_function *autoload_func; 
  32.     zend_bool full_tables_cleanup; 
  33.     /* for extended information support */ 
  34.     zend_bool no_extensions; 
  35. #ifdef ZEND_WIN32 
  36.     zend_bool timed_out; 
  37.     OSVERSIONINFOEX windows_version_info; 
  38. #endif 
  39.     HashTable regular_list; 
  40.     HashTable persistent_list; 
  41.     zend_vm_stack argument_stack; 
  42.     int user_error_handler_error_reporting; 
  43.     zval *user_error_handler; 
  44.     zval *user_exception_handler; 
  45.     zend_stack user_error_handlers_error_reporting; 
  46.     zend_ptr_stack user_error_handlers; 
  47.     zend_ptr_stack user_exception_handlers; 
  48.     zend_error_handling_t  error_handling; 
  49.     zend_class_entry      *exception_class; 
  50.     /* timeout support */ 
  51.     int timeout_seconds; 
  52.     int lambda_count; 
  53.     HashTable *ini_directives; 
  54.     HashTable *modified_ini_directives; 
  55.     zend_objects_store objects_store; 
  56.     zval *exception, *prev_exception; 
  57.     zend_op *opline_before_exception; 
  58.     zend_op exception_op[3]; 
  59.     struct _zend_execute_data *current_execute_data; 
  60.     struct _zend_module_entry *current_module; 
  61.     zend_property_info std_property_info; 
  62.     zend_bool active; 
  63.     void *saved_fpu_cw; 
  64.     void *reserved[ZEND_MAX_RESERVED_RESOURCES]; 
  65. }; 

這里我們只說兩個對我們比較重要的變量,active_op_array 和 current_execute_data.

active_op_array變量中保存了引擎正在執行的op_array(想了解什么是op_array請點擊查看),在Zend/zend_compile.h中有關于op_array的數據類型的定義,代碼如下:

  1. struct _zend_op_array { 
  2.     /* Common elements */ 
  3.     zend_uchar type; 
  4.     char *function_name; 
  5.     zend_class_entry *scope; 
  6.     zend_uint fn_flags; 
  7.     union _zend_function *prototype; 
  8.     zend_uint num_args; 
  9.     zend_uint required_num_args; 
  10.     zend_arg_info *arg_info; 
  11.     zend_bool pass_rest_by_reference; 
  12.     unsigned char return_reference; 
  13.     /* END of common elements */ 
  14.     zend_bool done_pass_two; 
  15.     zend_uint *refcount; 
  16.     zend_op *opcodes; 
  17.     zend_uint last, size; 
  18.     zend_compiled_variable *vars; 
  19.     int last_var, size_var; 
  20.     zend_uint T; 
  21.     zend_brk_cont_element *brk_cont_array; 
  22.     int last_brk_cont; 
  23.     int current_brk_cont; 
  24.     zend_try_catch_element *try_catch_array; 
  25.     int last_try_catch; 
  26.     /* static variables support */ 
  27.     HashTable *static_variables; 
  28.     zend_op *start_op; 
  29.     int backpatch_count; 
  30.     zend_uint this_var; 
  31.     char *filename; 
  32.     zend_uint line_start; 
  33.     zend_uint line_end; 
  34.     char *doc_comment; 
  35.     zend_uint doc_comment_len; 
  36.     zend_uint early_binding; /* the linked list of delayed declarations */ 
  37.     void *reserved[ZEND_MAX_RESERVED_RESOURCES]; 
  38. }; 

看完定義,就不用我多說了把,定義中,filename和 function_name分別保存了正在執行的文件名和方法名.

current_execute_data保存了正在執行的op_array的execute_data。execute_data保存了每個op_array執行過程中的一些數據,其定義在,Zend/zend_compile.h:

  1. struct _zend_execute_data { 
  2.     struct _zend_op *opline; 
  3.     zend_function_state function_state; 
  4.     zend_function *fbc; /* Function Being Called */ 
  5.     zend_class_entry *called_scope; 
  6.     zend_op_array *op_array; 
  7.     zval *object; 
  8.     union _temp_variable *Ts; 
  9.     zval ***CVs; 
  10.     HashTable *symbol_table; 
  11.     struct _zend_execute_data *prev_execute_data; 
  12.     zval *old_error_reporting; 
  13.     zend_bool nested; 
  14.     zval **original_return_value; 
  15.     zend_class_entry *current_scope; 
  16.     zend_class_entry *current_called_scope; 
  17.     zval *current_this;  //開源軟件:Vevb.com 
  18.     zval *current_object; 
  19.     struct _zend_op *call_opline; 
  20. }; 

定義中的opline就是正在執行的opcode,opcode的結構定義如下:

  1. struct _zend_op { 
  2.     opcode_handler_t handler; 
  3.     znode result; 
  4.     znode op1; 
  5.     znode op2; 
  6.     ulong extended_value; 
  7.     uint lineno; 
  8.     zend_uchar opcode; 
  9. }; 

其中lineno就是opcode所對應的行號.

示例說明:看完上面的數據結構定義,你是否已經知道如何找php正在執行的文件名,方法名和行號呢?如果還有疑問的話,那就接著看下面的例子,創建一個文件test.php,代碼如下:

  1. <?php 
  2. function test1(){ 
  3.         while(true){ 
  4.               sleep(1); 
  5.         } 
  6. test1(); 
  7. ?> 

cli方式執行php腳本,加入執行的進程號為14973,我們使用gdb命令來調試進程,代碼如下:

  1. $sudo gdb -p 14973 
  2. (gdb) print (char *)executor_globals.active_op_array->filename 
  3. $1 = 0x9853a34 "/home/xinhailong/test/php/test.php" 
  4. (gdb) print (char *)executor_globals.active_op_array->function_name 
  5. $2 = 0x9854db8 "test1" 
  6. (gdb) print executor_globals->current_execute_data->opline->lineno 
  7. $3 = 4 

很顯然,他正在執行第四行的sleep方法,如果上面的方法你感覺麻煩,那你可以使用.gdbinit文件,這個文件在php源碼的根目錄下,使用方法如下:

  1. $sudo gdb -p 14973 
  2. (gdb) source /home/xinhailong/.gdbinit 
  3. (gdb) zbacktrace 
  4. [0xa453f34] sleep(1) /home/xinhailong/test/php/test.php:4 
  5. [0xa453ed0] test1() /home/xinhailong/test/php/test.php:7 
  6. (gdb) 

題外話:從php5.6開始,php中集成了一個phpdbg的工具,可以像gdb調試c語言程序一樣.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武清区| 德阳市| 广水市| 肥西县| 阜康市| 丹阳市| 东至县| 保亭| 鹤庆县| 永兴县| 庄浪县| 五河县| 增城市| 新野县| 桐梓县| 普格县| 塔河县| 娱乐| 澄江县| 九寨沟县| 太白县| 民县| 曲麻莱县| 青田县| 三台县| 昆山市| 宝清县| 通江县| 益阳市| 盐山县| 电白县| 洪江市| 永嘉县| 武邑县| 修水县| 古交市| 吉隆县| 湖北省| 宾川县| 梅河口市| 五河县|