Successfully reported this slideshow.

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

7

Share

Loading in …3
×
1 of 83
1 of 83

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

7

Share

Download to read offline

Description

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.

Transcript

  1. 1. PHP 7 What changed internally? Nikita Popov
  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 Memory
  7. 7. Memory optimization • Reduce number of allocations • PHP 5 spends 20% of CPU time in the allocator Memory
  8. 8. Memory optimization • Reduce number of allocations • Reduce memory usage
  9. 9. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency
  10. 10. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU
  11. 11. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU L1D 1ns 32KB
  12. 12. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU 4ns L2 256 KB L1D 1ns 32KB
  13. 13. 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 CPU L312ns a few MB 4ns L2 256 KB L1D 1ns 32KB
  15. 15. 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
  16. 16. Memory optimization • Reduce number of allocations • Reduce memory usage • Reduce indirection
  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 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 (simple): null, bool, int, float ty zval
  20. 20. Zvals: PHP 5 • Zval = Type + Value value (complex) ty zval Complex data structure: string, array, object
  21. 21. Zvals: PHP 5 • Zval = Type + Value value (complex) ty zval Complex data structure: string, array, object $a = [];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” hash() “xyz” data key “xyz” Arrays: PHP 5 “bar”
  37. 37. [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
  38. 38. [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
  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 head tail
  40. 40. [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
  41. 41. [0]: (empty) [1]: [2]: (empty) [3]: “foo” hash() “bar” “xyz” Arrays: PHP 7 Bucket * uint32_t data key “foo” next data key “bar” next = NULL data key “xyz” next = NULL
  42. 42. [0]: (empty) [1]: [2]: (empty) [3]: hash() “bar” “xyz” Arrays: PHP 7 Bucket * uint32_t data key “foo” next data key “bar” next = NULL data key “xyz” next = NULL
  43. 43. [0]: (empty) [1]: [2]: (empty) [3]: hash() “bar” “xyz” Arrays: PHP 7 Bucket * uint32_t TOMBSTONE data key “bar” next = NULL data key “xyz” next = NULL
  44. 44. PHP 5 PHP 7 Allocations: 2 + 2 per element 2 + 0 per element Size: 72 + 112 per element 56 + 36 per element Indirections (lookup): 4 2 Arrays: PHP 5 vs. PHP 7 (For arrays with unique values)
  45. 45. PHP 5 PHP 7 Allocations: 2 + 2 per element 2 + 0 per element Size: 72 + 112 per element 56 + 36 per element Indirections (lookup): 4 2 Arrays: PHP 5 vs. PHP 7 (For arrays with unique values)
  46. 46. Immutable arrays $arrays = []; for ($i = 0; $i < 1000000; ++$i) { $arrays[] = [1, 2, 3, 4, 5, 6, 7, 8]; }
  47. 47. 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
  48. 48. 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
  49. 49. 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
  50. 50. Objects
  51. 51. Objects zval object store bucket actual object properties table PHP 5 property value
  52. 52. Objects zval object store bucket actual object properties table zval actual object properties table (including values) + PHP 5 PHP 7 property value
  53. 53. PHP 5 PHP 7 Allocations: 2 + 1 per property 1 + 0 per property Size: 96 + 40 per property 48 + 16 per property Indirections (prop val): 4 1 Objects: PHP 5 vs. PHP 7 (For objects with unique properties)
  54. 54. Integers
  55. 55. Integers 64-bit integers on 64-bit Windows
  56. 56. AST <?php $a = 42; $b = 24; echo $a + $b;
  57. 57. 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
  58. 58. 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
  59. 59. 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
  60. 60. 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
  61. 61. Virtual machine
  62. 62. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2);
  63. 63. 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()
  64. 64. 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
  65. 65. 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]
  66. 66. 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
  67. 67. 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
  68. 68. 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
  69. 69. 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
  70. 70. 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
  71. 71. 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
  72. 72. 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
  73. 73. 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
  74. 74. Virtual machine – inlined internal functions • Functions with custom opcodes: • strlen() • is_*() • defined() • call_user_func() • call_user_func_array()
  75. 75. 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);
  76. 76. 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()?
  77. 77. 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()!
  78. 78. Virtual machine – global registers zend_execute_data* execute_data; const zend_op* opline;
  79. 79. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15");
  80. 80. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15"); • Registers reserved in VM code
  81. 81. 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
  82. 82. 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
  83. 83. @nikita_ppv nikic@php.net https://joind.in/15255

Description

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.

Transcript

  1. 1. PHP 7 What changed internally? Nikita Popov
  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 Memory
  7. 7. Memory optimization • Reduce number of allocations • PHP 5 spends 20% of CPU time in the allocator Memory
  8. 8. Memory optimization • Reduce number of allocations • Reduce memory usage
  9. 9. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency
  10. 10. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU
  11. 11. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU L1D 1ns 32KB
  12. 12. Memory optimization • Reduce number of allocations • Reduce memory usage • Memory access has high latency CPU 4ns L2 256 KB L1D 1ns 32KB
  13. 13. 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 CPU L312ns a few MB 4ns L2 256 KB L1D 1ns 32KB
  15. 15. 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
  16. 16. Memory optimization • Reduce number of allocations • Reduce memory usage • Reduce indirection
  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 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 (simple): null, bool, int, float ty zval
  20. 20. Zvals: PHP 5 • Zval = Type + Value value (complex) ty zval Complex data structure: string, array, object
  21. 21. Zvals: PHP 5 • Zval = Type + Value value (complex) ty zval Complex data structure: string, array, object $a = [];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” hash() “xyz” data key “xyz” Arrays: PHP 5 “bar”
  37. 37. [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
  38. 38. [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
  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 head tail
  40. 40. [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
  41. 41. [0]: (empty) [1]: [2]: (empty) [3]: “foo” hash() “bar” “xyz” Arrays: PHP 7 Bucket * uint32_t data key “foo” next data key “bar” next = NULL data key “xyz” next = NULL
  42. 42. [0]: (empty) [1]: [2]: (empty) [3]: hash() “bar” “xyz” Arrays: PHP 7 Bucket * uint32_t data key “foo” next data key “bar” next = NULL data key “xyz” next = NULL
  43. 43. [0]: (empty) [1]: [2]: (empty) [3]: hash() “bar” “xyz” Arrays: PHP 7 Bucket * uint32_t TOMBSTONE data key “bar” next = NULL data key “xyz” next = NULL
  44. 44. PHP 5 PHP 7 Allocations: 2 + 2 per element 2 + 0 per element Size: 72 + 112 per element 56 + 36 per element Indirections (lookup): 4 2 Arrays: PHP 5 vs. PHP 7 (For arrays with unique values)
  45. 45. PHP 5 PHP 7 Allocations: 2 + 2 per element 2 + 0 per element Size: 72 + 112 per element 56 + 36 per element Indirections (lookup): 4 2 Arrays: PHP 5 vs. PHP 7 (For arrays with unique values)
  46. 46. Immutable arrays $arrays = []; for ($i = 0; $i < 1000000; ++$i) { $arrays[] = [1, 2, 3, 4, 5, 6, 7, 8]; }
  47. 47. 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
  48. 48. 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
  49. 49. 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
  50. 50. Objects
  51. 51. Objects zval object store bucket actual object properties table PHP 5 property value
  52. 52. Objects zval object store bucket actual object properties table zval actual object properties table (including values) + PHP 5 PHP 7 property value
  53. 53. PHP 5 PHP 7 Allocations: 2 + 1 per property 1 + 0 per property Size: 96 + 40 per property 48 + 16 per property Indirections (prop val): 4 1 Objects: PHP 5 vs. PHP 7 (For objects with unique properties)
  54. 54. Integers
  55. 55. Integers 64-bit integers on 64-bit Windows
  56. 56. AST <?php $a = 42; $b = 24; echo $a + $b;
  57. 57. 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
  58. 58. 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
  59. 59. 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
  60. 60. 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
  61. 61. Virtual machine
  62. 62. Virtual machine – stack management (PHP 5) function foo($a, $b) { return $a + $b; } foo(1, 2);
  63. 63. 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()
  64. 64. 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
  65. 65. 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]
  66. 66. 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
  67. 67. 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
  68. 68. 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
  69. 69. 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
  70. 70. 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
  71. 71. 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
  72. 72. 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
  73. 73. 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
  74. 74. Virtual machine – inlined internal functions • Functions with custom opcodes: • strlen() • is_*() • defined() • call_user_func() • call_user_func_array()
  75. 75. 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);
  76. 76. 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()?
  77. 77. 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()!
  78. 78. Virtual machine – global registers zend_execute_data* execute_data; const zend_op* opline;
  79. 79. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15");
  80. 80. Virtual machine – global registers register zend_execute_data* execute_data __asm__("%r14"); register const zend_op* opline __asm__("%r15"); • Registers reserved in VM code
  81. 81. 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
  82. 82. 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
  83. 83. @nikita_ppv nikic@php.net https://joind.in/15255

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

×