Successfully reported this slideshow.
Your SlideShare is downloading. ×

PHP 7 – What changed internally? (PHP Barcelona 2015)

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 88 Ad

PHP 7 – What changed internally? (PHP Barcelona 2015)

Download to read offline

One of the main selling points of PHP 7 is greatly improved performance, with many real-world applications now running twice as fast… But where do these improvements come from? At the core of PHP 7 lies an engine rewrite with focus on improving memory usage and performance. This talk provides an overview of the most significant changes, briefly covering everything from data structure changes, over enhancements in the executor, to the new compiler implementation.

One of the main selling points of PHP 7 is greatly improved performance, with many real-world applications now running twice as fast… But where do these improvements come from? At the core of PHP 7 lies an engine rewrite with focus on improving memory usage and performance. This talk provides an overview of the most significant changes, briefly covering everything from data structure changes, over enhancements in the executor, to the new compiler implementation.

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Similar to PHP 7 – What changed internally? (PHP Barcelona 2015) (20)

Advertisement

Recently uploaded (20)

PHP 7 – What changed internally? (PHP Barcelona 2015)

  1. 1. PHP 7 release Nov 12th * if everything goes as planned
  2. 2. http://hhvm.com/blog/9293/lockdown-results-and-hhvm-performance
  3. 3. Memory optimization
  4. 4. Memory optimization • Reduce number of allocations
  5. 5. Memory optimization • Reduce number of allocations Memory
  6. 6. Memory optimization • Reduce number of allocations • PHP 5 spends 20% of CPU time in the allocator Memory
  7. 7. Memory optimization • Reduce number of allocations • Reduce memory usage
  8. 8. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency
  9. 9. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU
  10. 10. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU L1D 1ns 32KB
  11. 11. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU 4ns L2 256 KB L1D 1ns 32KB
  12. 12. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU L312ns a few MB 4ns L2 256 KB L1D 1ns 32KB
  13. 13. RAM 100ns Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU L312ns a few MB 4ns L2 256 KB L1D 1ns 32KB
  14. 14. RAM 100ns Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency • Less data => more fits into the cache CPU L312ns a few MB 4ns L2 256 KB L1D 1ns 32KB
  15. 15. Memory optimization • Reduce number of allocations • Reduce memory usage • Reduce indirection
  16. 16. Memory optimization • Reduce number of allocations • Reduce memory usage • Reduce indirection • Pointer points to pointer pointing to pointer pointing to pointer pointing to pointer pointing to pointer pointing to what you actually want What you have What you want
  17. 17. Memory optimization • Reduce number of allocations • Reduce memory usage • Reduce indirection • Pointer points to pointer pointing to pointer pointing to pointer pointing to pointer pointing to pointer pointing to what you actually want • Fewer memory accesses What you have What you want
  18. 18. Zvals: PHP 5 • Zval = Type + Value value ty zval
  19. 19. Zvals: PHP 5 • Zval = Type + Value value ty zval $a = 42;Code:
  20. 20. Zvals: PHP 5 • Zval = Type + Value value = int(42) ty zval * zval $a: $a = 42;Code:
  21. 21. Zvals: PHP 5 • Zval = Type + Value value (simple): null, bool, int, float ty zval * zval $a: $a = 42;Code:
  22. 22. Zvals: PHP 5 • Zval = Type + Value value (complex) ty zval * zval $a: Complex data structure: string, array, object $a = [];Code:
  23. 23. Zvals: PHP 5 • Zval = Type + Value value (complex) ty zval * zval $a: Complex data structure: string, array, object $a = []; $b = $a; Code:
  24. 24. Zvals: PHP 5 • Zval = Type + Value + Refcount value (complex) refcount = 1 ty zval * zval $a: Complex data structure: string, array, object $a = []; $b = $a; Code:
  25. 25. Zvals: PHP 5 • Zval = Type + Value + Refcount value (complex) refcount = 2 ty zval * zval $a: Complex data structure: string, array, object $a = []; $b = $a; Code: zval *$b:
  26. 26. Zvals: PHP 7 • Zval = Type + Value value (complex) ty zval * zval $a: $a = []; $b = $a; Code: zval *$b: Complex data structure: string, array, object refcount = 2
  27. 27. Zvals: PHP 7 • Zval = Type + Value zval * zval $a: $a = []; $b = $a; Code: zval *$b: Complex data structure: string, array, object refcount = 2 value (complex) type_info
  28. 28. value (complex) type_info value (complex) type_info Zvals: PHP 7 • Zval = Type + Value $a: Complex data structure: string, array, object $b: refcount = 2 zval zval
  29. 29. PHP 5 PHP 7 value (simple): null, bool, int, float refcount ty gc_buffer zval * value (simple): … type_info 1 allocations 1 level of indirection 40 bytes no allocations no indirection 16 bytes
  30. 30. PHP 5 PHP 7 value (complex) refcount ty gc_root zval * Complex data structure: string, array, object value (complex) type_info Complex data structure: string, array, object refcount gc_info 2 allocations 2 levels of indirection 40 bytes 1 allocation 1 level of indirection 24 bytes
  31. 31. val (char *) len (int) A B C 0 zval value: PHP 5
  32. 32. zend_string * refcount gc_info hash len (size_t) A B C 0 val (char *) len (int) A B C 0 zval value: zval value: PHP 5 PHP 7
  33. 33. [0]: (empty) [1]: (empty) [2]: (empty) [3]: (empty) hash() “xyz” Arrays: PHP 5
  34. 34. [0]: (empty) [1]: [2]: (empty) [3]: (empty) hash() “xyz” data key “xyz” Arrays: PHP 5
  35. 35. [0]: (empty) [1]: [2]: (empty) [3]: “foo” data key “foo” hash() “xyz” data key “xyz” Arrays: PHP 5
  36. 36. [0]: (empty) [1]: [2]: (empty) [3]: “foo” data key “foo” next data key “bar” next = NULL hash() “bar” “xyz” data key “xyz” next = NULL Arrays: PHP 5
  37. 37. [0]: (empty) [1]: [2]: (empty) [3]: “foo” hash() “bar” “xyz” Arrays: PHP 5 head tail data key “foo” next data key “bar” next = NULL data key “xyz” next = NULL
  38. 38. [0]: (empty) [1]: [2]: (empty) [3]: “foo” hash() “bar” “xyz” Arrays: PHP 7 data key “foo” next data key “bar” next = NULL data key “xyz” next = NULL
  39. 39. [0]: (empty) [1]: [2]: (empty) [3]: “foo” hash() “bar” “xyz” Arrays: PHP 7 data key “foo” next data key “bar” next = NULL data key “xyz” next = NULL Bucket * uint32_t
  40. 40. PHP 5 without zval PHP 7 with zval Allocations: 2 + 1 per element 2 Size: 72 + 80 per element 56 + 36 per element Indirections (lookup): 4 2 Arrays: comparison
  41. 41. PHP 5 without zval PHP 7 with zval Allocations: 2 + 1 per element 2 Size: 72 + 80 per element 56 + 36 per element Indirections (lookup): 4 2 PHP 5 w/ unique zvals 2 + 2 per element 72 + 112 per element 4 Arrays: comparison
  42. 42. Immutable arrays $arrays = []; for ($i = 0; $i < 1000000; ++$i) { $arrays[] = [1, 2, 3, 4, 5, 6, 7, 8]; }
  43. 43. Immutable arrays $arrays = []; for ($i = 0; $i < 1000000; ++$i) { $arrays[] = [1, 2, 3, 4, 5, 6, 7, 8]; } PHP 5 Memory usage 1336 MB Execution time (create) 0.77 s Execution time (destroy) 1.45 s
  44. 44. Immutable arrays $arrays = []; for ($i = 0; $i < 1000000; ++$i) { $arrays[] = [1, 2, 3, 4, 5, 6, 7, 8]; } PHP 5 PHP 7 Memory usage 1336 MB 391 MB Execution time (create) 0.77 s 0.29 s Execution time (destroy) 1.45 s 0.05 s
  45. 45. Immutable arrays $arrays = []; for ($i = 0; $i < 1000000; ++$i) { $arrays[] = [1, 2, 3, 4, 5, 6, 7, 8]; } PHP 5 PHP 7 PHP 7 with opcache Memory usage 1336 MB 391 MB 32 MB Execution time (create) 0.77 s 0.29 s 0.03 s Execution time (destroy) 1.45 s 0.05 s 0.002 s
  46. 46. handle (ID) handlers zval value D V ac object dtor() free_storage() clone() handlers refcount gc_root ce properties properties_table guards [0] (stores $prop1) [1] (stores $prop2) [2] (stores $prop3) zval zval zval object store bucket Zend object Objects: PHP 5
  47. 47. zend_object * refcount type_info handle ce handlers properties value type_info value type_info value type_info $prop1 zval $prop2 zval $prop3 zval Zend object Objects: PHP 7
  48. 48. PHP 5 without zval PHP 7 with zval Allocations: 2 1 Size: 96 + 8 per element 48 + 16 per element Indirections (prop val): 4 1 Objects: comparison
  49. 49. Integers • long  zend_long • 64-bit integers on LLP64 platforms (= Windows)
  50. 50. AST <?php $a = 42; $b = 24; echo $a + $b;
  51. 51. AST <?php $a = 42; $b = 24; echo $a + $b; <?php T_OPEN_TAG $a T_VARIABLE = 42 T_LNUMBER ; $b T_VARIABLE = 24 T_LNUMBER ; echo T_ECHO $a T_VARIABLE + $b T_VARIABLE ; lex
  52. 52. AST <?php $a = 42; $b = 24; echo $a + $b; <?php T_OPEN_TAG $a T_VARIABLE = 42 T_LNUMBER ; $b T_VARIABLE = 24 T_LNUMBER ; echo T_ECHO $a T_VARIABLE + $b T_VARIABLE ; ASSIGN $a 42 ASSIGN $b 24 ADD $a $b ~2 ECHO ~2 RETURN 1 lex parse + compile
  53. 53. AST <?php $a = 42; $b = 24; echo $a + $b; <?php T_OPEN_TAG $a T_VARIABLE = 42 T_LNUMBER ; $b T_VARIABLE = 24 T_LNUMBER ; echo T_ECHO $a T_VARIABLE + $b T_VARIABLE ; ASSIGN $a 42 ASSIGN $b 24 ADD $a $b ~2 ECHO ~2 RETURN 1 lex parse compile stmts assign var 42 $a assign $b echo + $a $b var 24
  54. 54. AST <?php $a = 42; $b = 24; echo $a + $b; <?php T_OPEN_TAG $a T_VARIABLE = 42 T_LNUMBER ; $b T_VARIABLE = 24 T_LNUMBER ; echo T_ECHO $a T_VARIABLE + $b T_VARIABLE ; ASSIGN $a 42 ASSIGN $b 24 ADD $a $b ~0 ECHO ~0 RETURN 1 lex parse compile token_get_all() nikic/php-ast phpdbg -p stmts assign var 42 $a assign $b echo + $a $b var 24
  55. 55. Virtual machine
  56. 56. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2);
  57. 57. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2); SEND_VAL 1 SEND_VAL 2 DO_FCALL foo RECV $a RECV $b ADD $a $b ~0 RETURN ~0 {main} foo()
  58. 58. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2); SEND_VAL 1 SEND_VAL 2 DO_FCALL foo RECV $a RECV $b ADD $a $b ~0 RETURN ~0 {main} foo() … VM stack
  59. 59. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2); SEND_VAL 1 SEND_VAL 2 DO_FCALL foo RECV $a RECV $b ADD $a $b ~0 RETURN ~0 {main} foo() … int(1) int(2) VM stack arg[0] arg[1]
  60. 60. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2); SEND_VAL 1 SEND_VAL 2 DO_FCALL foo RECV $a RECV $b ADD $a $b ~0 RETURN ~0 {main} foo() … int(1) int(2) execute_data VM stack arg[0] arg[1] ~0 $a $b
  61. 61. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2); SEND_VAL 1 SEND_VAL 2 DO_FCALL foo RECV $a RECV $b ADD $a $b ~0 RETURN ~0 {main} foo() … int(1) int(2) execute_data int(1) int(2) VM stack arg[0] arg[1] ~0 $a $b
  62. 62. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2); SEND_VAL 1 SEND_VAL 2 DO_FCALL foo RECV $a RECV $b ADD $a $b ~0 RETURN ~0 {main} foo() … int(1) int(2) int(3) execute_data int(1) int(2) VM stack arg[0] arg[1] ~0 $a $b
  63. 63. Virtual machine – stack management (PHP 7) function foo($a, $b) { return $a + $b; } foo(1, 2); {main} foo() … VM stack INIT_FCALL foo SEND_VAL 1 SEND_VAL 2 DO_FCALL RECV $a RECV $b ADD $a $b ~0 RETURN ~0
  64. 64. Virtual machine – stack management (PHP 7) function foo($a, $b) { return $a + $b; } foo(1, 2); {main} foo() … execute_data VM stack ~0 $a $b INIT_FCALL foo SEND_VAL 1 SEND_VAL 2 DO_FCALL RECV $a RECV $b ADD $a $b ~0 RETURN ~0
  65. 65. Virtual machine – stack management (PHP 7) function foo($a, $b) { return $a + $b; } foo(1, 2); {main} foo() … execute_data int(1) int(2) VM stack ~0 $a $b INIT_FCALL foo SEND_VAL 1 SEND_VAL 2 DO_FCALL RECV $a RECV $b ADD $a $b ~0 RETURN ~0
  66. 66. Virtual machine – stack management (PHP 7) function foo($a, $b) { return $a + $b; } foo(1, 2); {main} foo() … execute_data int(1) int(2) VM stack ~0 $a $b INIT_FCALL foo SEND_VAL 1 SEND_VAL 2 DO_FCALL RECV $a RECV $b ADD $a $b ~0 RETURN ~0
  67. 67. Virtual machine – stack management (PHP 7) function foo($a, $b) { return $a + $b; } foo(1, 2); {main} foo() … execute_data int(1) int(2) int(3) VM stack ~0 $a $b INIT_FCALL foo SEND_VAL 1 SEND_VAL 2 DO_FCALL RECV $a RECV $b ADD $a $b ~0 RETURN ~0
  68. 68. Virtual machine – inlined internal functions • Functions with custom opcodes: • strlen() • is_*() • defined() • call_user_func() • call_user_func_array()
  69. 69. Virtual machine – inlined internal functions • Functions with custom opcodes: • strlen() • is_*() • defined() • call_user_func() • call_user_func_array() • Only in global scope or for fully qualified calls namespace foo; echo strlen($str);
  70. 70. Virtual machine – inlined internal functions • Functions with custom opcodes: • strlen() • is_*() • defined() • call_user_func() • call_user_func_array() • Only in global scope or for fully qualified calls namespace foo; echo strlen($str); Is this strlen() or foostrlen()?
  71. 71. Virtual machine – inlined internal functions • Functions with custom opcodes: • strlen() • is_*() • defined() • call_user_func() • call_user_func_array() • Only in global scope or for fully qualified calls namespace foo; echo strlen($str); This is definitely strlen()!
  72. 72. Virtual machine – global registers zend_execute_data* execute_data; const zend_op* opline;
  73. 73. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15");
  74. 74. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15"); • Registers reserved in VM code
  75. 75. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15"); • Registers reserved in VM code • Avoid reloading from executor_globals / execute_data
  76. 76. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15"); • Registers reserved in VM code • Avoid reloading from executor_globals / execute_data • Avoid save/restore during calls
  77. 77. Opcache
  78. 78. Opcache • File cache
  79. 79. Opcache • File cache • Alternative (or addition) to SHM
  80. 80. Opcache • File cache • Alternative (or addition) to SHM • Shared hosting? PHP restart / cache reset?
  81. 81. Opcache • File cache • Alternative (or addition) to SHM • Shared hosting? PHP restart / cache reset? • Time for 500 sequential WP 4.1 requests SHM 3 s File cache 6 s No cache 24 s
  82. 82. Opcache • Huge Pages
  83. 83. Opcache • Huge Pages • Code segment of PHP binary remapped into huge pages • Reduces iTLB misses
  84. 84. Opcache • Huge Pages • Code segment of PHP binary remapped into huge pages • Reduces iTLB misses CPU L2L1I …
  85. 85. Opcache • Huge Pages • Code segment of PHP binary remapped into huge pages • Reduces iTLB misses CPU L2L1I L1 iTLB 4K … L2 TLB
  86. 86. Opcache • Huge Pages • Code segment of PHP binary remapped into huge pages • Reduces iTLB misses CPU L2L1I L1 iTLB 4K L1 iTLB 2M … L2 TLB
  87. 87. @nikita_ppv nikic@php.net https://joind.in/talk/view/15865

×