PHP Performance SfLive 2010

8,071 views
7,839 views

Published on

Php performance presentation on symfony live

Published in: Technology
0 Comments
11 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
8,071
On SlideShare
0
From Embeds
0
Number of Embeds
1,290
Actions
Shares
0
Downloads
174
Comments
0
Likes
11
Embeds 0
No embeds

No notes for slide

PHP Performance SfLive 2010

  1. PHP Performances De Cock Xavier
  2. Who am I? <ul><li>PECL Developer </li><ul><li>BBCode extension
  3. Various in house extensions </li></ul><li>Swiftmailer contributor </li><ul><li>Started to work on swiftmailer for performance issues. </li></ul></ul>
  4. What is PHP ? <ul><li>Scripting langage
  5. Scripting engine </li><ul><li>Zend Engine
  6. Extensions providing functionalities </li></ul></ul>
  7. Zend Engine <ul><li>Memory representation of datas
  8. Source code compilation to Opcode
  9. Opcode Handling
  10. Memory management </li></ul>
  11. Meet The Zval <ul><li>Zval is the way ZE Stores values </li></ul>
  12. Benefits <ul><li>The Zval use </li><ul><li>Copy on write
  13. Automatic type conversion
  14. Automatic garbage collection when ref_count is 0
  15. As of PHP 5.3 Cyclic garbage collector </li></ul></ul>
  16. Zval Examples <?php $a = 41 ; /* Context (&quot;a&quot; => Zval_1); * Zval_1 {ref_count:1, value:41, type:LONG}; */ $b = $a ; /* Context (&quot;a&quot; => Zval_1, &quot;b&quot; => Zval_1); * Zval_1 {ref_count:2, value:41, type:LONG}; */ $b ++ ; /* Context (&quot;a&quot;=> Zval_1, &quot;b&quot; => Zval_2); * Zval_1 {ref_count:1, value:41, type:LONG}; * Zval_2 {ref_count:1, value:42, type:LONG}; */ $b .= &quot;, The answer ...&quot; ; /* Context (&quot;a&quot;=> Zval_1, &quot;b&quot; => Zval_3); * Zval_1 {ref_count:1, value:41, type:LONG}; * Zval_2 {ref_count:0, value:42, type:LONG}; // Freed * Zval_3 {ref_count:1, value:&quot;42, The answer ...&quot;, type:STRING}; */
  17. Don't try to outsmart ZE <ul><li>Working by reference will usually make you waste memory as it can trigger more easily the copy on write </li></ul>< ?php $a = 1 ; /* Zval {val:1; ref_count:1; is_ref:f} */ $b = & $a ; /* Zval {val:1; ref_count:2; is_ref: t } */ print ( $b ); /* This is a pass by value function, so, * what's send to print is : * Zval2 {val:1 ref_count:1; is_ref:f } */
  18. Zend Op <ul><li>Opcode is the “machine langage” of ZE
  19. What's in a zend_op </li><ul><li>OpCode
  20. Op1
  21. Op2
  22. Metas (line n°, handler, result, ...) </li></ul></ul>
  23. Opcode examples <?php echo &quot;Hello&quot;, &quot; &quot;, &quot;World&quot;; filename: /home/xavier/- function name: (null) number of ops: 5 compiled vars: none line # op operands --------------------------------------------- 2 0 ECHO OP1[ 'Hello' ] 1 ECHO OP1[ ' ' ] 2 ECHO OP1[ 'World' ] 4 3 RETURN OP1[ 1 ] 4* ZEND_HANDLE_EXCEPTION
  24. Opcode examples <?php echo &quot;Hello&quot;.&quot; &quot;.&quot;World&quot;; filename: /home/xavier/- function name: (null) number of ops: 5 compiled vars: none line # op return operands --------------------------------------- 2 0 CONCAT RES[ ~0 ] OP1[ 'Hello' ] OP2[ '+' ] 1 CONCAT RES[ ~1 ] OP1[ ~0 ] OP2[ 'World' ] 2 ECHO OP1[ ~1 ] 3 3 RETURN OP1[ 1 ] 4* ZEND_HANDLE_EXCEPTION
  25. Hash Tables <ul><li>Everythings basically stays in an hash table </li><ul><li>Symbol Tables (Local / global Variables)
  26. Arrays
  27. Object Properties
  28. Ini Directives, included Files
  29. Classes, Functions, Constants </li></ul></ul>
  30. Hash Tables <ul><li>Pros: </li><ul><li>2 quick access patterns </li><ul><li>Get value by key
  31. Table Traversal nest / previous item </li></ul><li>Count is a fast operation </li></ul><li>Cons: </li><ul><li>Not able to browse by value </li></ul></ul>
  32. Garbage collector <ul><li>PHP 5.3 includes a Garbage collector that break reference cycle.
  33. PHP 5.2 does not include a GC </li><ul><li>Avoid creating cycles
  34. Break them before unset
  35. Try to keep in mind what can hold ref </li></ul><li>Keep in mind what handle ref: </li><ul><li>Closures, Callback, Ressources, ... </li></ul></ul>
  36. SwiftMailer Examples Implementation 1 foreach ( unpack ('C*' , $bytes ) as $byte ) // Convert String to int array { $this -> _array [] = pack ('C' , $byte ); // Function Call in tight loop } filename: /home/xavier/Bureau/php-5.3.1/ext/- function name: (null) number of ops: 17 compiled vars: !0 = $bytes, !1 = $byte line # op return operands ----------------------------------------------- 2 0 SEND_VAL OP1[ 'C*' ] 1 SEND_VAR OP1[ !0 ] 2 DO_FCALL OP1[ 'unpack' ] 3 FE_RESET RES[ $1 ] OP1[ $0 ] OP2[ ->14 ] 4 FE_FETCH RES[ $2 ] OP1[ $1 ] OP2[ ->14 ] 5 ZEND_OP_DATA RES[ UNUSED ] OP1[ UNUSED ] OP2[ UNUSED ] 6 ASSIGN OP1[ !1 ] OP2[ $2 ] 4 7 SEND_VAL OP1[ 'C' ] 8 SEND_VAR OP1[ !1 ] 9 DO_FCALL OP1[ 'pack' ] 10 FETCH_OBJ_W RES[ $4 ] OP1[ UNUSED ] OP2[ '_array' ] 11 ZEND_ASSIGN_DIM OP1[ $4 ] OP2[ UNUSED ] 12 ZEND_OP_DATA RES[ UNUSED ] OP1[ $6 ] OP2[ $7 ] 5 13 JMP OP1[ ->4 ] 14 SWITCH_FREE RES[ UNUSED ] OP1[ $1 ] 6 15 RETURN OP1[ 1 ] 16* ZEND_HANDLE_EXCEPTION
  37. SwiftMailer Examples Implementation 2 $to_add = str_split ( $bytes ); // Convert string to char array /* add the array as first arg of the function */ array_unshift ( $to_add , & $this -> _array ); // Will trigger E_STRICT /* Push all elements in one function call and get the count */ $this -> _arraySize = call_user_func_array ('array_push' , $to_add ); compiled vars: !0 = $to_add, !1 = $bytes line # op return operands -------------------------------------------------------------------------- 2 0 SEND_VAR OP1[ !1 ] 1 DO_FCALL OP1[ 'str_split' ] 2 ASSIGN OP1[ !0 ] OP2[ $0 ] 4 3 SEND_REF RES[ UNUSED ] OP1[ !0 ] OP2[ UNUSED ] 4 FETCH_OBJ_W RES[ $2 ] OP1[ UNUSED ] OP2[ '_array' ] 5 SEND_REF RES[ UNUSED ] OP1[ $2 ] OP2[ UNUSED ] 6 DO_FCALL OP1[ 'array_unshift' ] 6 7 SEND_VAL OP1[ 'array_push' ] 8 SEND_VAR OP1[ !0 ] 9 DO_FCALL OP1[ 'call_user_func_array' ] 10 ZEND_ASSIGN_OBJ OP1[ UNUSED ] OP2[ '_arraySize' ] 11 ZEND_OP_DATA RES[ UNUSED ] OP1[ $5 ] OP2[ UNUSED ] 7 12 RETURN OP1[ 1 ] 13* ZEND_HANDLE_EXCEPTION
  38. SwiftMailer Examples Implementation 3 $to_add = str_split ( $bytes ); // Convert string to char array /* Calls array Merge */ /* Array merge works by copying the first array element By element, then the second, third, … The speed decreases with the number of items in each array */ $this -> _array = array_merge ( $this -> _array , $to_add ); $this -> _arraySize = count ( $this -> _array ); compiled vars: !0 = $to_add, !1 = $bytes line # op return operands ------------------------------------------------------------------------------- 2 0 SEND_VAR OP1[ !1 ] 1 DO_FCALL OP1[ 'str_split' ] 2 ASSIGN OP1[ !0 ] OP2[ $0 ] 7 3 FETCH_OBJ_R RES[ $3 ] OP1[ UNUSED ] OP2[ '_array' ] 4 SEND_VAR OP1[ $3 ] 5 SEND_VAR OP1[ !0 ] 6 DO_FCALL OP1[ 'array_merge' ] 7 ZEND_ASSIGN_OBJ OP1[ UNUSED ] OP2[ '_array' ] 8 ZEND_OP_DATA RES[ UNUSED ] OP1[ $4 ] OP2[ UNUSED ] 8 9 FETCH_OBJ_R RES[ $6 ] OP1[ UNUSED ] OP2[ '_array' ] 10 SEND_VAR OP1[ $6 ] 11 DO_FCALL OP1[ 'count' ] 12 ZEND_ASSIGN_OBJ OP1[ UNUSED ] OP2[ '_arraySize' ] 13 ZEND_OP_DATA RES[ UNUSED ] OP1[ $7 ] OP2[ UNUSED ] 10 14 RETURN OP1[ 1 ] 15* ZEND_HANDLE_EXCEPTION
  39. SwiftMailer Examples Implementation 4 $to_add = str_split ( $bytes ); foreach ( $to_add as $value ) { $this -> _array [] = $value ; } $this -> _arraySize = count ( $this -> _array ); compiled vars: !0 = $to_add, !1 = $bytes, !2 = $value line # op return operands -------------------------------------------------------------------------- 1 0 SEND_VAR OP1[ !1 ] 1 DO_FCALL OP1[ 'str_split' ] 2 ASSIGN OP1[ !0 ] OP2[ $0 ] 2 3 FE_RESET RES[ $2 ] OP1[ !0 ] OP2[ ->11 ] 4 FE_FETCH RES[ $3 ] OP1[ $2 ] OP2[ ->11 ] 5 ZEND_OP_DATA RES[ UNUSED ] OP1[ UNUSED ] OP2[ UNUSED ] 6 ASSIGN OP1[ !2 ] OP2[ $3 ] 3 7 FETCH_OBJ_W RES[ $5 ] OP1[ UNUSED ] OP2[ '_array' ] 8 ZEND_ASSIGN_DIM OP1[ $5 ] OP2[ UNUSED ] 9 ZEND_OP_DATA RES[ UNUSED ] OP1[ !2 ] OP2[ $7 ] 4 10 JMP OP1[ ->4 ] 11 SWITCH_FREE RES[ UNUSED ] OP1[ $2 ] 5 12 FETCH_OBJ_R RES[ $9 ] OP1[ UNUSED ] OP2[ '_array' ] 13 SEND_VAR OP1[ $9 ] 14 DO_FCALL OP1[ 'count' ] 15 ZEND_ASSIGN_OBJ OP1[ UNUSED ] OP2[ '_arraySize' ] 16 ZEND_OP_DATA RES[ UNUSED ] OP1[ $10 ] OP2[ UNUSED ] 6 17 RETURN OP1[ 1 ] 18* ZEND_HANDLE_EXCEPTION
  40. How to optimize? <ul><li>Be efficient: </li><ul><li>Optimize tight loops, one line functions
  41. Highly covered source code (profile your app) </li></ul><li>Use tools </li><ul><li>Vulcan Logic Dumper (pecl vld)
  42. Xdebug / Zend Debug – Profilers </li></ul></ul>
  43. Other ways <ul><li>Use built-in functions (except array_* and in_array)
  44. Use Opcode Caching : APC, eAccelerator, XCache, Zend Server, …
  45. Use data Caching : Memcached,
  46. Optimize your SQL
  47. Access your data by batches
  48. Create PHP Extension
  49. Use other implementations : Facebook's HipHop, phc, Quercus, RoadSend PHP </li></ul>
  50. Questions? Thanks for listening

×