Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

PHP 7 – What changed internally?

11,273 views

Published on

As a result of an engine rewrite with focus on more efficient data structures, PHP 7 offers much improved performance and memory usage. This session describes important aspects of the new implementation and how it compares to PHP 5. A particular focus will be on the representation of values, arrays and objects.

Published in: Technology
  • Be the first to comment

PHP 7 – What changed internally?

  1. 1. PHP 7 What changed internally? Nikita Popov
  2. 2. •Return type declarations •Scalar type declarations function startsWith(string $s1, string $s2) : bool {…}
  3. 3. 211 254 256 273 627 666 0 100 200 300 400 500 600 700 PHP 5.3 PHP 5.4 PHP 5.5 PHP 5.6 PHP 7 HHVM 3.7 Req/Sec Wordpress 4.1.1 (home, 20 c) Stolen from Rasmus
  4. 4. •Smaller data structures •Fewer allocations •Less indirection
  5. 5. zval
  6. 6. zval 5
  7. 7. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE 5
  8. 8. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE lval (long) dval (double) 5
  9. 9. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE lval (long) dval (double) 5 64 bits / 8 bytes
  10. 10. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE lval (long) dval (double) lval (long) 1 bit 5
  11. 11. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE val (char *) len (int) A B C 0 5
  12. 12. value ty 5
  13. 13. value refcount ty 5
  14. 14. value = LONG(42) refcount = 1$i $i = 42; 5
  15. 15. value = LONG(42) refcount = 2$i $j $i = 42; $j = $i; 5
  16. 16. value = LONG(42) refcount = 3$i $j $k $i = 42; $j = $i; $k = $i; 5
  17. 17. value = LONG(42) refcount = 1 $i = 42; $j = $i; $k = $i; unset($i, $k); 5 $j
  18. 18. value = LONG(42) refcount = 0 $i = 42; $j = $i; $k = $i; unset($i, $k); unset($j); 5
  19. 19. value = LONG(42) refcount = 0 $i = 42; $j = $i; $k = $i; unset($i, $k); unset($j); free( ) 5
  20. 20. value = ARRAY refcount = 1$a $a = []; 5 [0]: (empty) [1]: (empty) [2]: (empty) …
  21. 21. value = ARRAY refcount = 2$a $a = []; $a[0] = $a; 5 [0]: [1]: (empty) [2]: (empty) …
  22. 22. value = ARRAY refcount = 1 $a = []; $a[0] = $a; unset($a); 5 [0]: [1]: (empty) [2]: (empty) …
  23. 23. value = ARRAY refcount = 1 $a = []; $a[0] = $a; unset($a); 5 [0]: [1]: (empty) [2]: (empty) … [0]: (empty) [1]: (empty) [2]: (empty) … GC root buffer
  24. 24. value = ARRAY refcount = 1 $a = []; $a[0] = $a; unset($a); 5 [0]: [1]: (empty) [2]: (empty) … [0]: [1]: (empty) [2]: (empty) … GC root buffer
  25. 25. value = ARRAY refcount = 1 gc_root $a = []; $a[0] = $a; unset($a); 5 [0]: [1]: (empty) [2]: (empty) … [0]: [1]: (empty) [2]: (empty) … GC root buffer
  26. 26. value refcount ty gc_root 5
  27. 27. size prev_size value refcount ty gc_root 5
  28. 28. size prev_size value refcount ty gc_root 5 32 bytes 16 bytes
  29. 29. value type_info (u2) 7
  30. 30. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE 5
  31. 31. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE 7 FALSE TRUE
  32. 32. NULL BOOL LONG DOUBLE STRING ARRAY OBJECT RESOURCE REFERENCE 7 FALSE TRUE
  33. 33. NULL FALSE TRUE LONG DOUBLE STRING ARRAY OBJECT RESOURCE REFERENCE val (char *) len (int) A B C 0 5
  34. 34. NULL FALSE TRUE LONG DOUBLE STRING ARRAY OBJECT RESOURCE REFERENCE 7 zend_string * refcount type_info hash len (size_t) A B C 0
  35. 35. NULL FALSE TRUE LONG DOUBLE STRING ARRAY OBJECT RESOURCE REFERENCE 7 zend_string * refcount type_info hash len (size_t) A B C 0 refcounted header
  36. 36. $i = 42; 7 $i value = 42 LONG
  37. 37. $i = 42; $j = $i; 7 $i value = 42 LONG $j value = 42 LONG
  38. 38. $i = 42; $j = $i; $k = $i; 7 $i value = 42 LONG $j value = 42 LONG $k value = 42 LONG
  39. 39. $s = “foobar”; 7 $s value STRING refcount = 1 type_info hash = 0x80000652FDE460BE len = 6 f o o b a r 0
  40. 40. $s = “foobar”; $t = $s; 7 $s value STRING $t value STRING refcount = 2 type_info hash = 0x80000652FDE460BE len = 6 f o o b a r 0
  41. 41. $s = “foobar”; $t = $s; $u = $s; 7 $s value STRING $t value STRING $u value STRING refcount = 3 type_info hash = 0x80000652FDE460BE len = 6 f o o b a r 0
  42. 42. 7 refcount type_info hash len (size_t) A B C 0 refcounted header
  43. 43. 7 refcount type_info hash len (size_t) A B C 0 refcounted header type flags gc_info
  44. 44. 7 refcount type_info hash len (size_t) A B C 0 refcounted header type flags gc_info INTERNED etc.
  45. 45. value type_info (u2) 7
  46. 46. value type_info (u2) 7 type type_flags const_flags
  47. 47. 7 type type_flags const_flags refcounted collectable copyable simple types string interned string array object resource reference
  48. 48. 7 type type_flags const_flags refcounted collectable copyable simple types string  interned string array  object  resource  reference 
  49. 49. 7 type type_flags const_flags refcounted collectable copyable simple types string  interned string array   object   resource  reference 
  50. 50. 7 type type_flags const_flags refcounted collectable copyable simple types string   interned string array    object   resource  reference 
  51. 51. 5 array == HashTable
  52. 52. 5 key = “foo” idx = hash(“foo”)
  53. 53. 5 key = “foo” idx = hash(“foo”) % tableSize
  54. 54. 5 [0]: (empty) [1]: (empty) [2]: (empty) [3]: (empty) “foo”
  55. 55. 5 [0]: (empty) [1]: [2]: (empty) [3]: (empty) “foo” data key “foo” zval
  56. 56. 5 [0]: (empty) [1]: [2]: (empty) [3]: (empty) “foo” data key “foo” “bar”
  57. 57. 5 [0]: (empty) [1]: [2]: (empty) [3]: (empty) “foo” data key “foo” next “bar” data key “bar” next = NULL
  58. 58. 5 [0]: (empty) [1]: [2]: (empty) [3]: (empty) “foo” data key “foo” next prev = NULL “bar” data key “bar” next = NULL prev
  59. 59. 5 data prev next key “foo” zval
  60. 60. 5 data listNext listPrev prev next key “foo” zval $a1 = [“foo” => 1, “bar” => 2]; $a2 = [“bar” => 2, “foo” => 1];
  61. 61. 5 dataPtr data listNext listPrev prev next key “foo” zval
  62. 62. 5 hash keyLen dataPtr data listNext listPrev prev next key “foo” zval
  63. 63. 7 hash key value type_info next zval
  64. 64. 7 hash key value type_info next refcount type_info hash len f o o 0 zend_string
  65. 65. 7 hash key value type_info next hash key value type_info next hash key value type_info next
  66. 66. 7 hash key value type_info next hash key value type_info next hash key value type_info next [0] [1] [2] [3]
  67. 67. 7 hash key value type_info next hash key value type_info next hash key value type_info next [0] = -1 [1] = -1 [2] = -1 [3] = -1 $a = []; numUsed = 0
  68. 68. 7 hash key value = 42 LONG next = -1 hash key value type_info next hash key value type_info next [0] = -1 [1] = 0 [2] = -1 [3] = -1 “foo” $a = []; $a[“foo”] = 42; “foo” numUsed = 1
  69. 69. 7 hash key value = 42 LONG next = -1 hash key value = 24 LONG next = -1 hash key value type_info next [0] = -1 [1] = 0 [2] = -1 [3] = 1 “foo” $a = []; $a[“foo”] = 42; $a[“bar”] = 24; “foo” “bar” “bar” numUsed = 2
  70. 70. 7 hash key value = 42 LONG next = 2 hash key value = 24 LONG next = -1 hash key value = 3.141 DOUBLE next = -1 [0] = -1 [1] = 0 [2] = -1 [3] = 1 “foo” $a = []; $a[“foo”] = 42; $a[“bar”] = 24; $a[“xyz”] = 3.141; “foo” “bar” “bar” “xyz” “xyz”
  71. 71. 7 hash key value UNDEF next = -1 hash key value = 24 LONG next = -1 hash key value = 3.141 DOUBLE next = -1 [0] = -1 [1] = 2 [2] = -1 [3] = 1 $a = []; $a[“foo”] = 42; $a[“bar”] = 24; $a[“xyz”] = 3.141; unset($a[“foo”]); “bar” “bar” “xyz” “xyz”
  72. 72. 7 hash key value type_info next hash key value type_info next [0] [1] [2] [3] [4] [5] [6] [7]
  73. 73. 7 hash key value type_info next hash key value type_info next [0] [1] [2] [3] [4] [5] [6] [7]
  74. 74. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1]
  75. 75. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data
  76. 76. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info data / hash pointer numUsed
  77. 77. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info tableMask data / hash pointer numUsed tableSize tableMask = -tableSize
  78. 78. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info tableMask data / hash pointer numUsed tableSize 1010111010110110 tableMask = -tableSize
  79. 79. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info tableMask data / hash pointer numUsed tableSize 1010111010110110 | 1111111111100000 tableMask = -tableSize
  80. 80. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info tableMask data / hash pointer numUsed tableSize 1010111010110110 | 1111111111100000 = 1111111111110110 = -10 tableMask = -tableSize
  81. 81. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info tableMask data / hash pointer numUsed numElems tableSize nextFreeElement
  82. 82. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info tableMask data / hash pointer numUsed numElems tableSize internalPtr nextFreeElement destructor
  83. 83. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info flags tableMask data / hash pointer numUsed numElems tableSize internalPtr nextFreeElement destructor flags applyCnt iterCnt
  84. 84. 7 hash key value type_info next hash key value type_info next [-8] [-7] [-6] [-5] [-4] [-3] [-2] [-1] hash data refcount type_info flags tableMask data / hash pointer numUsed numElems tableSize internalPtr nextFreeElement destructor flags applyCnt iterCnt PACKED etc.
  85. 85. 7 hash key value type_info next hash key value type_info next data refcount type_info flags tableMask data pointer numUsed numElems tableSize internalPtr nextFreeElement destructor flags applyCnt iterCnt PACKED etc.
  86. 86. 5 objects
  87. 87. 5 handle (ID) handlers zval value
  88. 88. 5 handle (ID) handlers zval value handler table object store bucket
  89. 89. 5 handle (ID) handlers zval value … read_prop() write_prop() … object store bucket
  90. 90. 5 handle (ID) handlers zval value … read_prop() write_prop() … object object store bucket actual object
  91. 91. 5 handle (ID) handlers zval value … read_prop() write_prop() … object refcount object store bucket actual object
  92. 92. 5 handle (ID) handlers zval value … read_prop() write_prop() … object dtor() free_storage() clone() refcount object store bucket actual object
  93. 93. 5 handle (ID) handlers zval value … read_prop() write_prop() … object dtor() free_storage() clone() handlers refcount gc_root object store bucket actual object
  94. 94. 5 handle (ID) handlers zval value … read_prop() write_prop() … D V ac object dtor() free_storage() clone() handlers refcount gc_root object store bucket actual object
  95. 95. 5 object store bucket standard object
  96. 96. 5 object store bucket ce standard object zend_class_entry
  97. 97. 5 object store bucket ce properties standard object zend_class_entry HashTable for dynamic properties
  98. 98. 5 object store bucket ce properties properties_table standard object zend_class_entry HashTable for dynamic properties [0] (stores $prop1) [1] (stores $prop2) [2] (stores $prop3) zval zval zval
  99. 99. 5 object store bucket ce properties properties_table guards standard object zend_class_entry HashTable for dynamic properties [0] (stores $prop1) [1] (stores $prop2) [2] (stores $prop3) zval zval zval HashTable for __get etc. guards
  100. 100. 5 object store bucket ce properties properties_table guards custom extension for internal object standard object zend_class_entry HashTable for dynamic properties [0] (stores $prop1) [1] (stores $prop2) [2] (stores $prop3) zval zval zval HashTable for __get etc. guards
  101. 101. 7 zend_object * refcount type_info ce properties zend_class_entry HashTable for dynamic properties
  102. 102. 7 zend_object * refcount type_info handle ce handlers properties zend_class_entry HashTable for dynamic properties handler table
  103. 103. 7 zend_object * refcount type_info handle ce handlers properties zend_class_entry HashTable for dynamic properties handler table object store
  104. 104. 7 zend_object * refcount type_info handle ce handlers properties value type_info value type_info value type_info zend_class_entry HashTable for dynamic properties$prop1 zval $prop2 zval $prop3 zval handler table object store
  105. 105. 7 zend_object * refcount type_info handle ce handlers properties value type_info value type_info value type_info zend_class_entry HashTable for dynamic properties HashTable for __get etc. guards guards zval $prop1 zval $prop2 zval handler table object store
  106. 106. 7 zend_object * refcount type_info handle ce handlers properties value type_info value type_info value type_info zend_class_entry HashTable for dynamic properties HashTable for __get etc. guards guards zval $prop1 zval $prop2 zval handler table object store ext. for internal objects
  107. 107. 7 zend_object * refcount type_info handle ce handlers properties value type_info value type_info value type_info zend_class_entry HashTable for dynamic properties HashTable for __get etc. guards guards zval $prop1 zval $prop2 zval handler table object store ext. for internal objects offset
  108. 108. 7 zend_object * refcount type_info handle ce handlers properties value type_info value type_info value type_info guards zval $prop1 zval $prop2 zval object store ext. for internal objects offset … handlers table offset
  109. 109. 7 zend_object * refcount type_info handle ce handlers properties value type_info value type_info value type_info guards zval $prop1 zval $prop2 zval object store ext. for internal objects offset free() dtor() clone() … handlers table offset
  110. 110. 5 references
  111. 111. value = LONG(42) refcount = 3$i $j $k $i = 42; $j = $i; $k = $i; 5
  112. 112. value = LONG(42) refcount = 2$i $k $i = 42; $j = $i; $k = $i; $k++; 5 value = LONG(43) refcount = 1 $j
  113. 113. value = LONG(42) refcount = 2$i $k $i = 42; $j = $i; $k = $i; $k++; 5 value = LONG(43) refcount = 1 $j copy-on-write (COW)
  114. 114. value = LONG(42) refcount = 3 is_ref = 1$i $j $k $i = 42; $j =& $i; $k =& $i; 5
  115. 115. value = LONG(43) refcount = 3 is_ref = 1$i $j $k $i = 42; $j =& $i; $k =& $i; $k++; 5
  116. 116. $i = 42; $j =& $i; $k =& $i; 7 $i value REFERENCE $j value REFERENCE $k value REFERENCE refcount = 3 type_info value = 42 LONG zend_reference
  117. 117. $a = range( 0,1000000); $r =& $a; 7 $a value REFERENCE $r value REFERENCE refcount = 2 type_info value ARRAY zend_reference refcount = 1 type_info … zend_array
  118. 118. $a = range( 0,1000000); $r =& $a; $v = $a; 7 $a value REFERENCE $r value REFERENCE $v value ARRAY refcount = 2 type_info value ARRAY zend_reference refcount = 2 type_info … zend_array
  119. 119. PHP 5 PHP 7 zval 32 bytes 16 bytes HashTable element 80 bytes 36 bytes (incl. zval) HashTable 72 bytes 56 bytes object 96 bytes 40 bytes
  120. 120. PHP 5 PHP 7 zval 32 bytes 16 bytes HashTable element 80 bytes 36 bytes (incl. zval) HashTable 72 bytes 56 bytes object 96 bytes 40 bytes fewer allocations less indirection
  121. 121. PHP 7 Alpha 1 June 11th
  122. 122. @nikita_ppv nikic@php.net

×