PageRenderTime 244ms CodeModel.GetById 165ms app.highlight 21ms RepoModel.GetById 23ms app.codeStats 0ms

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

http://github.com/facebook/hiphop-php
PHP | 254 lines | 203 code | 38 blank | 13 comment | 30 complexity | 3cc8853aa2b030d427499c337b3ee1c8 MD5 | raw file
  1<?hh
  2
  3class RootClass {
  4  public darray<string, mixed> $children = darray[];
  5  <<__Memoize>>
  6  public static function getInstance() {
  7    return new RootClass();
  8  }
  9}
 10$r = RootClass::getInstance();
 11
 12class ChildWithClosureMember {
 13  public $closure;
 14  public function doWork() {
 15    json_encode($this->closure);
 16  }
 17}
 18
 19class ParentWithClosureTarget {
 20  public $someval = 20151012;
 21  public $somestring = "";
 22  public $child;
 23
 24  public function __construct() {
 25    $this->somestring = json_encode(varray[1,2,3]);
 26    $this->child = new ChildWithClosureMember();
 27    $this->child->closure = $this->createClosure();
 28  }
 29
 30  public function createClosure() {
 31    return function() {
 32      return $this->someval;
 33    };
 34  }
 35}
 36$r->children['MemoizedSingleton'] = new ParentWithClosureTarget();
 37$r->children['MemoizedSingleton']->child->doWork();
 38
 39class ClassForSecondCapture { }
 40
 41// We do some consolidation here because the behavior when testing
 42// is really non-deterministic. Both on order of scans and also
 43// whether things are in CPP or PHP (based on mode of test)
 44ObjprofHeapgraphPhp::$echobuf = varray[];
 45function echo_buffer($str) {
 46
 47  // new root names
 48  $str = str_replace('HPHP::CppStack', 'onsome-stack', $str);
 49  $str = str_replace('HPHP::PhpStack', 'onsome-stack', $str);
 50  $str = str_replace('HPHP::RdsLocal', 'rds-local', $str);
 51  ObjprofHeapgraphPhp::$echobuf[] = $str;
 52}
 53function echo_flush() {
 54
 55  $echobuf_uniq = array_unique(ObjprofHeapgraphPhp::$echobuf);
 56  sort(inout $echobuf_uniq);
 57  foreach ($echobuf_uniq as $str) {
 58    echo $str;
 59  }
 60  ObjprofHeapgraphPhp::$echobuf = varray[];
 61}
 62
 63ObjprofHeapgraphPhp::$hg_for_closure = null;
 64ObjprofHeapgraphPhp::$id_of_rootclass = null;
 65function showTestClasses($node) {
 66
 67
 68
 69  $classname = idx($node, 'class', 'no class...');
 70  $kind = $node['kind'];
 71  $testclasses = darray[
 72    ChildWithClosureMember::class => 1,
 73    ParentWithClosureTarget::class => 1,
 74    RootClass::class => 1,
 75    ClassForSecondCapture::class => 1,
 76  ];
 77  if ($kind === "Object" && idx($testclasses, $classname)) {
 78    echo_buffer("$classname\n");
 79    $same_node = heapgraph_node(ObjprofHeapgraphPhp::$hg_for_closure, $node['index']);
 80    $same_class = idx($same_node, 'class', 'null');
 81    if ($same_class != $classname) {
 82      echo "heapgraph_node broken: $classname != $same_class\n";
 83    }
 84
 85    if ($classname == "RootClass") {
 86      ObjprofHeapgraphPhp::$id_of_rootclass = $node['index'];
 87    }
 88  }
 89}
 90
 91function edgeName($hg, $edge) {
 92  $from = $edge['from'];
 93  $n = heapgraph_node($hg, $from);
 94  $kind = $n['kind'];
 95  if ($kind === 'Root') {
 96    $ty = $n['type'];
 97    if ($ty === 'HPHP::CppStack') return 'onsome-stack';
 98    if ($ty === 'HPHP::PhpStack') return 'onsome-stack';
 99    if ($ty === 'HPHP::StaticPropData') {
100      return "StaticProperty:".$n['class']."::".$n['prop'];
101    }
102  }
103  if (isset($edge['key'])) return "Key:".$edge['key'];
104  if (isset($edge['value'])) return "Value:".$edge['value'];
105  if (isset($edge['prop'])) return "Property:".$edge['prop'];
106  if (isset($edge['offset'])) return "Offset:".$edge['offset'];
107  return "";
108}
109
110function showTestEdge($edge) {
111
112  $testedges = darray[
113    'ArrayKey:MemoizedSingleton' => 1,
114    'Property:somestring' => 1,
115    'Property:child' => 1,
116    'Property:closure' => 1,
117    'Property:children' => 1,
118  ];
119  $name = edgeName(ObjprofHeapgraphPhp::$hg_for_closure, $edge);
120  if (idx($testedges, $name)) {
121    echo_buffer("$name\n");
122    $same_edge = heapgraph_edge(ObjprofHeapgraphPhp::$hg_for_closure, $edge['index']);
123    if ($same_edge != $edge) {
124      echo"heapgraph_edge broken: $edge != $same_edge\n";
125    }
126  }
127}
128
129function showAllEdges($hg, $edges) {
130  foreach ($edges as $edge) {
131    echo_buffer(edgeName($hg, $edge)."\n");
132  }
133}
134
135function showClassOnly($node) {
136  if (idx($node, 'class')) {
137    echo_buffer($node['class']."\n");
138  }
139}
140
141function showClass($node) {
142  if (idx($node, 'class')) {
143    echo_buffer($node['class']."\n");
144  } else {
145    echo_buffer($node['kind']."\n");
146  }
147}
148
149function printNode($node) {
150  echo "node ".$node['index']." ".$node['kind']." ";
151  if (isset($node['class'])) echo $node['class']." ";
152  if (isset($node['func'])) echo $node['func']." ";
153  if (isset($node['local'])) echo $node['local']." ";
154  if (isset($node['prop'])) echo $node['prop']." ";
155  echo "\n";
156}
157
158function printEdge($edge) {
159  echo 'edge '.$edge['name'].' ';
160  echo $edge['kind'].' '.$edge['from']."->".$edge['to'];
161  echo "\n";
162}
163
164ObjprofHeapgraphPhp::$visited = varray[];
165function dfsPrintNode($hg, $node) {
166
167  $id = $node['index'];
168  ObjprofHeapgraphPhp::$visited[$id] = true;
169  printNode($node);
170  $in_edges = heapgraph_node_in_edges($hg, $id);
171  foreach ($in_edges as $edge) {
172    printEdge($edge);
173  }
174  foreach ($in_edges as $edge) {
175    $from = $edge['from'];
176    if (!isset(ObjprofHeapgraphPhp::$visited[$from])) {
177      dfsPrintNode($hg, heapgraph_node($hg, $from));
178    }
179  }
180}
181
182////////////////////////////////////////////////////
183// Test starts here:
184
185echo "Capturing two snapshots...\n";
186// FIRST CAPTURE
187$hg = heapgraph_create();
188var_dump($hg);
189
190// SECOND CAPTURE
191$b = new ClassForSecondCapture();
192$hg2 = heapgraph_create();
193var_dump($hg2);
194
195// STATS
196echo "Stats for first capture:\n";
197$stats = heapgraph_stats($hg);
198var_dump($stats);
199
200// OUT OF BOUNDS
201echo "Getting invalid nodes and edges:\n";
202$inv_edge = heapgraph_edge($hg, -1) ?: heapgraph_edge($hg, 999999);
203$inv_node = heapgraph_node($hg, -1) ?: heapgraph_node($hg, 999999);
204echo $inv_edge ?: $inv_node ?: "Invalid nodes and edges work OK.\n";
205echo_flush();
206
207// TRAVERSAL
208echo "\nTraversing second capture:\n";
209ObjprofHeapgraphPhp::$hg_for_closure = $hg2;
210heapgraph_foreach_node($hg2, 'showTestClasses');
211echo_flush();
212
213echo "\nTraversing first capture:\n";
214ObjprofHeapgraphPhp::$hg_for_closure = $hg;
215heapgraph_foreach_node($hg, 'showTestClasses');
216echo_flush();
217
218echo "\nTraversing edges for first capture:\n";
219ObjprofHeapgraphPhp::$hg_for_closure = $hg;
220heapgraph_foreach_edge($hg, 'showTestEdge');
221echo_flush();
222
223echo "\nTraversing roots for first capture:\n";
224heapgraph_foreach_root($hg, 'showTestEdge');
225echo_flush();
226
227// CHILDREN / PARENTS
228echo "\nGetting in edges of root class:\n";
229$in_edges = heapgraph_node_in_edges($hg, ObjprofHeapgraphPhp::$id_of_rootclass);
230showAllEdges($hg, $in_edges);
231echo_flush();
232
233echo "\nGetting out edges of root class:\n";
234$out_edges = heapgraph_node_out_edges($hg, ObjprofHeapgraphPhp::$id_of_rootclass);
235showAllEdges($hg, $out_edges);
236echo_flush();
237
238// DFS NODES
239echo "\nDoing DFS from root class on nodes:\n";
240heapgraph_dfs_nodes($hg, varray[ObjprofHeapgraphPhp::$id_of_rootclass], varray[], 'showClassOnly');
241echo_flush();
242
243echo "\nDoing DFS from root class on nodes (skipping root):\n";
244heapgraph_dfs_nodes(
245  $hg, varray[ObjprofHeapgraphPhp::$id_of_rootclass], varray[ObjprofHeapgraphPhp::$id_of_rootclass], 'showClass'
246);
247echo_flush();
248
249abstract final class ObjprofHeapgraphPhp {
250  public static $echobuf;
251  public static $hg_for_closure;
252  public static $id_of_rootclass;
253  public static $visited;
254}