@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3/**
4 * @phutil-external-symbol function xhprof_compute_flat_info
5 */
6final class PhabricatorXHProfProfileTopLevelView
7 extends PhabricatorXHProfProfileView {
8
9 private $profileData;
10 private $limit;
11 private $file;
12
13 public function setProfileData(array $data) {
14 $this->profileData = $data;
15 return $this;
16 }
17
18 public function setLimit($limit) {
19 $this->limit = $limit;
20 return $this;
21 }
22
23 public function setFile(PhabricatorFile $file) {
24 $this->file = $file;
25 return $this;
26 }
27
28 public function render() {
29 DarkConsoleXHProfPluginAPI::includeXHProfLib();
30
31 $GLOBALS['display_calls'] = true;
32 $totals = array();
33 $flat = xhprof_compute_flat_info($this->profileData, $totals);
34 unset($GLOBALS['display_calls']);
35
36 $aggregated = array();
37 foreach ($flat as $call => $counters) {
38 $parts = explode('@', $call, 2);
39 $agg_call = reset($parts);
40 if (empty($aggregated[$agg_call])) {
41 $aggregated[$agg_call] = $counters;
42 } else {
43 foreach ($aggregated[$agg_call] as $key => $val) {
44 if ($key != 'wt') {
45 $aggregated[$agg_call][$key] += $counters[$key];
46 }
47 }
48 }
49 }
50 $flat = $aggregated;
51
52 $flat = isort($flat, 'wt');
53 $flat = array_reverse($flat);
54
55 $rows = array();
56 $rows[] = array(
57 pht('Total'),
58 number_format($totals['ct']),
59 number_format($totals['wt']).' us',
60 '100.0%',
61 number_format($totals['wt']).' us',
62 '100.0%',
63 );
64
65 if ($this->limit) {
66 $flat = array_slice($flat, 0, $this->limit);
67 }
68
69 foreach ($flat as $call => $counters) {
70 $rows[] = array(
71 $this->renderSymbolLink($call),
72 number_format($counters['ct']),
73 number_format($counters['wt']).' us',
74 sprintf('%.1f%%', 100 * $counters['wt'] / $totals['wt']),
75 number_format($counters['excl_wt']).' us',
76 sprintf('%.1f%%', 100 * $counters['excl_wt'] / $totals['wt']),
77 );
78 }
79
80 Javelin::initBehavior('phabricator-tooltips');
81
82 $table = new AphrontTableView($rows);
83 $table->setHeaders(
84 array(
85 pht('Symbol'),
86 pht('Count'),
87 javelin_tag(
88 'span',
89 array(
90 'sigil' => 'has-tooltip',
91 'meta' => array(
92 'tip' => pht(
93 'Total wall time spent in this function and all of '.
94 'its children (children are other functions it called '.
95 'while executing).'),
96 'size' => 200,
97 ),
98 ),
99 pht('Wall Time (Inclusive)')),
100 '%',
101 javelin_tag(
102 'span',
103 array(
104 'sigil' => 'has-tooltip',
105 'meta' => array(
106 'tip' => pht(
107 'Wall time spent in this function, excluding time '.
108 'spent in children (children are other functions it '.
109 'called while executing).'),
110 'size' => 200,
111 ),
112 ),
113 pht('Wall Time (Exclusive)')),
114 '%',
115 ));
116 $table->setColumnClasses(
117 array(
118 'wide pri',
119 'n',
120 'n',
121 'n',
122 'n',
123 'n',
124 ));
125
126 $panel = new PHUIObjectBoxView();
127 $header = id(new PHUIHeaderView())
128 ->setHeader(pht('XHProf Profile'));
129
130 if ($this->file) {
131 $button = id(new PHUIButtonView())
132 ->setHref($this->file->getBestURI())
133 ->setText(pht('Download %s Profile', '.xhprof'))
134 ->setTag('a');
135 $header->addActionLink($button);
136 }
137
138 $panel->setHeader($header);
139 $panel->setTable($table);
140
141 return $panel->render();
142 }
143}