/hphp/test/slow/objprof/objprof.php

https://gitlab.com/iranjith4/hhvm · PHP · 237 lines · 202 code · 17 blank · 18 comment · 35 complexity · f972f14a38a38ee7d51f2645bacd98c4 MD5 · raw file

  1. <?hh
  2. // If anything breaks, it's should be easier to debug by running shell:
  3. // #export TRACE=objprof:3
  4. function get_instances(string $cls, ?array $objs) {
  5. if (!$objs) return 0;
  6. return hphp_array_idx(hphp_array_idx($objs, $cls, array()), "instances", 0);
  7. }
  8. function get_bytes_eq(string $cls, ?array $objs) {
  9. if (!$objs) return 0;
  10. $bytes = get_bytes($cls, $objs);
  11. $bytesd = get_bytesd($cls, $objs);
  12. if ($bytes != $bytesd) {
  13. echo "(BAD) Normalized bytes mismatch: ".var_export($objs, true)."\n";
  14. }
  15. return $bytes;
  16. }
  17. function get_bytes(string $cls, ?array $objs) {
  18. if (!$objs) return 0;
  19. return hphp_array_idx(hphp_array_idx($objs, $cls, array()), "bytes", 0);
  20. }
  21. function get_bytesd(string $cls, ?array $objs) {
  22. if (!$objs) return 0;
  23. return hphp_array_idx(hphp_array_idx($objs, $cls, array()),
  24. "bytes_normalized", 0);
  25. }
  26. function getStr(int $len): string {
  27. $ret = "";
  28. for ($i = 0; $i < $len; ++$i) {
  29. $ret .= "X";
  30. }
  31. return $ret;
  32. }
  33. // TEST: tracking works when enabled and not when disabled
  34. class EmptyClass {}
  35. $myClass2 = new EmptyClass(); // ++
  36. $objs = objprof_get_data();
  37. $emptyCount = get_instances("EmptyClass", $objs);
  38. echo $emptyCount ? "(GOOD) Tracking when enabled\n" :
  39. "(BAD) Not tracking when enabled: \n".var_export($objs, true)."\n";
  40. $ObjSize = get_bytes("EmptyClass", $objs) / $emptyCount;
  41. $objs = null;
  42. // TEST: nullifying variables removes their tracking
  43. class EmptyClass2 {}
  44. $myClass = new EmptyClass2(); // -- ++
  45. $myClass2 = new EmptyClass2(); // -- ++
  46. $objs = objprof_get_data();
  47. $instances_before = get_instances("EmptyClass2", $objs);
  48. echo $instances_before == 2
  49. ? "(GOOD) Tracking works\n"
  50. : "(BAD) Tracking failed: ".var_export($objs, true)."\n";
  51. $objs = null;
  52. $myClass = null; // --
  53. $myClass2 = null; // --
  54. $objs = objprof_get_data();
  55. $instances_after = get_instances("EmptyClass2", $objs);
  56. echo $instances_after
  57. ? "(BAD) Untracking failed: ".var_export($objs, true)."\n"
  58. : "(GOOD) Untracking works\n";
  59. $objs = null;
  60. // TEST: sizes of classes (including private props)
  61. class SimpleProps { // 19+16+16 = 51
  62. private string $prop1 = "one"; // 3 (byte x char) + 16 (TypedValue bytes) = 19
  63. protected int $prop2 = 2; // 16
  64. public bool $prop3 = true; // 16
  65. }
  66. $myClass = new SimpleProps(); // ++
  67. $objs = objprof_get_data();
  68. echo get_bytes('SimpleProps', $objs) == $ObjSize + 19 + 16 + 16 && // 83
  69. get_bytesd('SimpleProps', $objs) == 51 + $ObjSize - 3 // String is static
  70. ? "(GOOD) Bytes (props) works\n"
  71. : "(BAD) Bytes (props) failed: ".var_export($objs, true)."\n";
  72. $objs = null;
  73. // TEST: sizes of arrays
  74. class SimpleArrays {
  75. public array $arrEmpty = array(); // 16 (tv) + 16 (ArrayData) = 32
  76. public array $arrMixed = array( // 32 (ArrayData) + 46 + 32 = 110
  77. "somekey" => "someval", // 2 * (7 chars + 16 bytes object) = 46
  78. 321 => 3, // 16 * 2 = 32
  79. );
  80. public array<int> $arrNums = array(
  81. 2012,
  82. 2013,
  83. 2014
  84. ); // 32 + (16 * 3) = 80
  85. }
  86. $myClass = new SimpleArrays();
  87. $objs = objprof_get_data();
  88. echo get_bytes('SimpleArrays', $objs) == $ObjSize + 80 + 110 + 32 && // 254
  89. get_bytesd('SimpleArrays', $objs) == $ObjSize + (16 * 3) // 3 Static Arrays
  90. ? "(GOOD) Bytes (arrays) works\n"
  91. : "(BAD) Bytes (arrays) failed: ".var_export($objs, true)."\n";
  92. $objs = null;
  93. // TEST: sizes of dynamic props
  94. class DynamicClass {}
  95. $myClass = new DynamicClass();
  96. $dynamic_field = 'abcd'; // 16 + 4
  97. $dynamic_field2 = 1234; // 16 + 4 (dynamic properties - always string)
  98. $myClass->$dynamic_field = 1; // 16
  99. $myClass->$dynamic_field2 = 1; // 16
  100. $objs = objprof_get_data();
  101. echo get_bytes('DynamicClass', $objs) == $ObjSize + 20 + 20 + 32 && // 104
  102. get_bytesd('DynamicClass', $objs) == $ObjSize + 72 - 4 - 4
  103. ? "(GOOD) Bytes (dynamic) works\n"
  104. : "(BAD) Bytes (dynamic) failed: ".var_export($objs, true)."\n";
  105. $objs = null;
  106. // TEST: async handle
  107. async function myAsyncFunc(): Awaitable<int> { return 42; }
  108. $myClass = myAsyncFunc();
  109. $objs = objprof_get_data();
  110. echo get_bytes_eq(StaticWaitHandle::class, $objs) == 16 + $ObjSize // handle size
  111. ? "(GOOD) Bytes (Async) works\n"
  112. : "(BAD) Bytes (Async) failed: ".var_export($objs, true)."\n";
  113. $objs = null;
  114. // TEST: map with int and string keys (Mixed)
  115. $myClass = Map{};
  116. $MapSize = get_bytes('HH\Map', objprof_get_data());
  117. $myClass = Map {
  118. "abc" => 1, // 3 + 16 + 16 = 35
  119. 1 => "22", // 16 + 16 + 2 = 34
  120. 1234123 => 3 // 16 + 16 = 32
  121. };
  122. $objs = objprof_get_data();
  123. echo get_bytes('HH\\Map', $objs) == $MapSize + 32 + 34 + 35 && // MapSize+101
  124. get_bytesd('HH\\Map', $objs) == $MapSize+101 - 2 - 3 // Static strings
  125. ? "(GOOD) Bytes (Mixed Map) works\n"
  126. : "(BAD) Bytes (Mixed Map) failed: ".var_export($objs, true)."\n";
  127. $objs = null;
  128. // TEST: vector with int and string vals (Packed)
  129. $myClass = Vector {
  130. "abc", // 3 + 16 = 19
  131. 1, // 16
  132. };
  133. $objs = objprof_get_data();
  134. echo get_bytes('HH\\Vector', $objs) == $ObjSize + 32 + 3 && // Vec+35
  135. get_bytesd('HH\\Vector', $objs) == $ObjSize + 32 // Static strings
  136. ? "(GOOD) Bytes (Vector) works\n"
  137. : "(BAD) Bytes (Vector) failed: ".var_export($objs, true)."\n";
  138. $objs = null;
  139. // TEST: set with int and string keys
  140. $myClass = Set{};
  141. $SetSize = get_bytes('HH\Set', objprof_get_data());
  142. $myClass = Set {
  143. getStr(3), // (3 + 16) * 2 = 38
  144. getStr(4), // (4 + 16) * 2 = 40
  145. };
  146. $objs = objprof_get_data();
  147. echo get_bytes('HH\\Set', $objs) == $SetSize + 78 && // SetSize + 38+40
  148. get_bytesd('HH\\Set', $objs) == $SetSize+78 -3-4 // SetSize+ 38+40
  149. ? "(GOOD) Bytes (Set) works\n"
  150. : "(BAD) Bytes (Set) failed: ".var_export($objs, true)."\n";
  151. $objs = null;
  152. // TEST: basic ref count
  153. $myClass = Map {
  154. getStr(19) => getStr(17),
  155. };
  156. $objs = objprof_get_data();
  157. echo get_bytes_eq('HH\\Map', $objs) == $MapSize + 19+17+16+16 // MapSize+35=109
  158. ? "(GOOD) Bytes (RefCount) works\n"
  159. : "(BAD) Bytes (RefCount) failed: ".var_export($objs, true)."\n";
  160. $objs = null;
  161. // TEST: multiple ref counted strings
  162. $mystr = getStr(9); // inc 1
  163. class SharedStringClass {
  164. public string $val_ref = null;
  165. public function __construct(string $str) {
  166. $this->val_ref = $str; // inc 2 + inc 3
  167. }
  168. }
  169. $myClass = new SharedStringClass($mystr);
  170. $myClass2 = new SharedStringClass($mystr);
  171. $objs = objprof_get_data();
  172. echo get_bytes('SharedStringClass', $objs) == 2 * ($ObjSize + 9 + 16) && // 114
  173. get_bytesd('SharedStringClass', $objs) == 2 * $ObjSize + 32 + (2 * 3)
  174. ? "(GOOD) Bytes (SharedString) works\n"
  175. : "(BAD) Bytes (SharedString) failed: ".var_export($objs, true)."\n";
  176. $objs = null;
  177. // TEST: multiple ref counted arrays
  178. $my_arr = array( // 32 + 88 = 120
  179. getStr(4) => getStr(8), // 4 + 8 + 16 + 16 = 44
  180. getStr(5) => getStr(7), // 5 + 7 + 16 + 16 = 44
  181. );
  182. class SharedArrayClass {
  183. public array $val_ref = null;
  184. public function __construct(array $arr) {
  185. $this->val_ref = $arr;
  186. }
  187. }
  188. $myClass = new SharedArrayClass($my_arr);
  189. $myClass2 = new SharedArrayClass($my_arr);
  190. $my_arr = null;
  191. $objs = objprof_get_data();
  192. echo get_bytes('SharedArrayClass', $objs) == ($ObjSize + 120) * 2 && // 152 * 2
  193. get_bytesd('SharedArrayClass', $objs) == $ObjSize + 120 + $ObjSize + 16 //
  194. ? "(GOOD) Bytes (SharedArray) works\n"
  195. : "(BAD) Bytes (SharedArray) failed: ".var_export($objs, true)."\n";
  196. $objs = null;
  197. $myClass = null;
  198. $myClass2 = null;
  199. // TEST: multiple ref counted nested arrays
  200. $my_arr = array( // 32 + 76 = 108
  201. array(getStr(4) => getStr(8)), // 4 + 8 + 16 + 16 = 44 + 32 = 76
  202. );
  203. class NestedArrayClass {
  204. public array $val_ref = null;
  205. public function __construct(array $arr) {
  206. $this->val_ref = $arr;
  207. }
  208. }
  209. $myClass = new NestedArrayClass($my_arr);
  210. $my_arr = null;
  211. $objs = objprof_get_data();
  212. echo get_bytes_eq('NestedArrayClass', $objs) == ($ObjSize + 108) // 140
  213. ? "(GOOD) Bytes (NestedArray) works\n"
  214. : "(BAD) Bytes (NestedArray) failed: ".var_export($objs, true)."\n";
  215. $objs = null;
  216. $myClass = null;
  217. // LAST TEST: Dont crash on custom types
  218. //$xml = simplexml_load_string('<root><hello>world</hello></root>');
  219. //$objs = objprof_get_data();
  220. echo "(GOOD) Got here without crashing\n";