PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/profiling/Controller.php

https://github.com/netplayer/PrestaShop
PHP | 653 lines | 578 code | 46 blank | 29 comment | 51 complexity | a3366e6181c00fed09e96bfdd09dd886 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * 2007-2014 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@prestashop.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  18. * versions in the future. If you wish to customize PrestaShop for your
  19. * needs please refer to http://www.prestashop.com for more information.
  20. *
  21. * @author PrestaShop SA <contact@prestashop.com>
  22. * @copyright 2007-2014 PrestaShop SA
  23. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  24. * International Registered Trademark & Property of PrestaShop SA
  25. */
  26. function developpementErrorHandler($errno, $errstr, $errfile, $errline)
  27. {
  28. if (!(error_reporting() & $errno))
  29. return;
  30. switch($errno)
  31. {
  32. case E_ERROR:
  33. echo '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  34. break;
  35. case E_WARNING:
  36. echo '[PHP Warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  37. break;
  38. case E_PARSE:
  39. echo '[PHP Parse #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  40. break;
  41. case E_NOTICE:
  42. echo '[PHP Notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  43. break;
  44. case E_CORE_ERROR:
  45. echo '[PHP Core #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  46. break;
  47. case E_CORE_WARNING:
  48. echo '[PHP Core warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  49. break;
  50. case E_COMPILE_ERROR:
  51. echo '[PHP Compile #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  52. break;
  53. case E_COMPILE_WARNING:
  54. echo '[PHP Compile warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  55. break;
  56. case E_USER_ERROR:
  57. echo '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  58. break;
  59. case E_USER_WARNING:
  60. echo '[PHP User warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  61. break;
  62. case E_USER_NOTICE:
  63. echo '[PHP User notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  64. break;
  65. case E_STRICT:
  66. echo '[PHP Strict #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  67. break;
  68. case E_RECOVERABLE_ERROR:
  69. echo '[PHP Recoverable error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  70. break;
  71. default:
  72. echo '[PHP Unknown error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')';
  73. }
  74. die;
  75. return true;
  76. }
  77. abstract class Controller extends ControllerCore
  78. {
  79. public $_memory = array();
  80. public $_time = array();
  81. private static $_footer = true;
  82. public static function disableParentCalls()
  83. {
  84. self::$_footer = false;
  85. }
  86. private function displayMemoryColor($n)
  87. {
  88. $n /= 1048576;
  89. if ($n > 3)
  90. return '<span style="color:red">'.sprintf('%0.2f', $n).'</span>';
  91. if ($n > 1)
  92. return '<span style="color:orange">'.sprintf('%0.2f', $n).'</span>';
  93. return '<span style="color:green">'.sprintf('%0.2f', $n).'</span>';
  94. }
  95. private function displayPeakMemoryColor($n)
  96. {
  97. $n /= 1048576;
  98. if ($n > 16)
  99. return '<span style="color:red">'.sprintf('%0.1f', $n).'</span>';
  100. if ($n > 12)
  101. return '<span style="color:orange">'.sprintf('%0.1f', $n).'</span>';
  102. return '<span style="color:green">'.sprintf('%0.1f', $n).'</span>';
  103. }
  104. private function displaySQLQueries($n)
  105. {
  106. if ($n > 150)
  107. return '<span style="color:red">'.$n.' queries</span>';
  108. if ($n > 100)
  109. return '<span style="color:orange">'.$n.' queries</span>';
  110. return '<span style="color:green">'.$n.' quer'.($n == 1 ? 'y' : 'ies').'</span>';
  111. }
  112. private function displayRowsBrowsed($n)
  113. {
  114. if ($n > 400)
  115. return '<span style="color:red">'.$n.' rows browsed</span>';
  116. if ($n > 100)
  117. return '<span style="color:orange">'.$n.' rows browsed</span>';
  118. return '<span style="color:green">'.$n.' row'.($n == 1 ? '' : 's').' browsed</span>';
  119. }
  120. private function displayLoadTimeColor($n, $kikoo = false)
  121. {
  122. if ($n > 1)
  123. return '<span style="color:red">'.round($n * 1000).'</span>'.($kikoo ? ' ms<br />You\'d better run your shop on a toaster' : '');
  124. if ($n > 0.5)
  125. return '<span style="color:orange">'.round($n * 1000).'</span>'.($kikoo ? ' ms<br />I hope it is a shared hosting' : '');
  126. return '<span style="color:green">'.round($n * 1000).'</span>'.($kikoo ? ' ms<br />Good boy! That\'s what I call a webserver!' : '');
  127. }
  128. private function getTimeColor($n)
  129. {
  130. if ($n > 4)
  131. return 'style="color:red"';
  132. if ($n > 2)
  133. return 'style="color:orange"';
  134. return 'style="color:green"';
  135. }
  136. private function getQueryColor($n)
  137. {
  138. if ($n > 5)
  139. return 'style="color:red"';
  140. if ($n > 2)
  141. return 'style="color:orange"';
  142. return 'style="color:green"';
  143. }
  144. private function getTableColor($n)
  145. {
  146. if ($n > 30)
  147. return 'style="color:red"';
  148. if ($n > 20)
  149. return 'style="color:orange"';
  150. return 'style="color:green"';
  151. }
  152. private function getObjectModelColor($n)
  153. {
  154. if ($n > 50)
  155. return 'style="color:red"';
  156. if ($n > 10)
  157. return 'style="color:orange"';
  158. return 'style="color:green"';
  159. }
  160. public function __construct()
  161. {
  162. //set_error_handler('developpementErrorHandler');
  163. ini_set('html_errors', 'on');
  164. ini_set('display_errors', 'on');
  165. error_reporting(E_ALL | E_STRICT);
  166. if (!self::$_footer)
  167. return;
  168. $this->_memory['config'] = memory_get_usage();
  169. $this->_mempeak['config'] = memory_get_peak_usage();
  170. $this->_time['config'] = microtime(true);
  171. parent::__construct();
  172. $this->_memory['constructor'] = memory_get_usage();
  173. $this->_mempeak['constructor'] = memory_get_peak_usage();
  174. $this->_time['constructor'] = microtime(true);
  175. }
  176. public function run()
  177. {
  178. $this->init();
  179. $this->_memory['init'] = memory_get_usage();
  180. $this->_mempeak['init'] = memory_get_peak_usage();
  181. $this->_time['init'] = microtime(true);
  182. if ($this->checkAccess())
  183. {
  184. $this->_memory['checkAccess'] = memory_get_usage();
  185. $this->_mempeak['checkAccess'] = memory_get_peak_usage();
  186. $this->_time['checkAccess'] = microtime(true);
  187. if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className)))
  188. $this->setMedia();
  189. $this->_memory['setMedia'] = memory_get_usage();
  190. $this->_mempeak['setMedia'] = memory_get_peak_usage();
  191. $this->_time['setMedia'] = microtime(true);
  192. // postProcess handles ajaxProcess
  193. $this->postProcess();
  194. $this->_memory['postProcess'] = memory_get_usage();
  195. $this->_mempeak['postProcess'] = memory_get_peak_usage();
  196. $this->_time['postProcess'] = microtime(true);
  197. if (!empty($this->redirect_after))
  198. $this->redirect();
  199. if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className)))
  200. $this->initHeader();
  201. $this->_memory['initHeader'] = memory_get_usage();
  202. $this->_mempeak['initHeader'] = memory_get_peak_usage();
  203. $this->_time['initHeader'] = microtime(true);
  204. $this->initContent();
  205. $this->_memory['initContent'] = memory_get_usage();
  206. $this->_mempeak['initContent'] = memory_get_peak_usage();
  207. $this->_time['initContent'] = microtime(true);
  208. if (!$this->content_only && ($this->display_footer || (isset($this->className) && $this->className)))
  209. $this->initFooter();
  210. $this->_memory['initFooter'] = memory_get_usage();
  211. $this->_mempeak['initFooter'] = memory_get_peak_usage();
  212. $this->_time['initFooter'] = microtime(true);
  213. // default behavior for ajax process is to use $_POST[action] or $_GET[action]
  214. // then using displayAjax[action]
  215. if ($this->ajax)
  216. {
  217. $action = Tools::getValue('action');
  218. if (!empty($action) && method_exists($this, 'displayAjax'.Tools::toCamelCase($action)))
  219. $this->{'displayAjax'.$action}();
  220. elseif (method_exists($this, 'displayAjax'))
  221. $this->displayAjax();
  222. }
  223. else
  224. $this->displayDebug();
  225. }
  226. else
  227. {
  228. $this->initCursedPage();
  229. $this->displayDebug();
  230. }
  231. }
  232. function ini_get_display_errors()
  233. {
  234. $a = 'display_errors';
  235. $b = ini_get($a);
  236. switch (strtolower($b))
  237. {
  238. case 'on':
  239. case 'yes':
  240. case 'true':
  241. return 'assert.active' !== $a;
  242. case 'stdout':
  243. case 'stderr':
  244. return 'display_errors' === $a;
  245. default:
  246. return (bool)(int)$b;
  247. }
  248. }
  249. private function sizeofvar($var)
  250. {
  251. $start_memory = memory_get_usage();
  252. try {
  253. $tmp = Tools::unSerialize(serialize($var));
  254. } catch (Exception $e) {
  255. $tmp = $this->getVarData($var);
  256. }
  257. $size = memory_get_usage() - $start_memory;
  258. return $size;
  259. }
  260. private function getVarData($var)
  261. {
  262. if (is_object($var))
  263. return $var;
  264. return (string)$var;
  265. }
  266. public function displayDebug()
  267. {
  268. global $start_time;
  269. $this->display();
  270. $this->_memory['display'] = memory_get_usage();
  271. $this->_mempeak['display'] = memory_get_peak_usage();
  272. $this->_time['display'] = microtime(true);
  273. if (!$this->ini_get_display_errors())
  274. return;
  275. $memory_peak_usage = memory_get_peak_usage();
  276. $hr = '<hr>';
  277. $totalSize = 0;
  278. foreach (get_included_files() as $file)
  279. $totalSize += filesize($file);
  280. $totalQueryTime = 0;
  281. foreach (Db::getInstance()->queries as $data)
  282. $totalQueryTime += $data['time'];
  283. $executedModules = Hook::getExecutedModules();
  284. $hooktime = Hook::getHookTime();
  285. arsort($hooktime);
  286. $totalHookTime = 0;
  287. foreach ($hooktime as $time)
  288. $totalHookTime += $time;
  289. $hookMemoryUsage = Hook::getHookMemoryUsage();
  290. arsort($hookMemoryUsage);
  291. $totalHookMemoryUsage = 0;
  292. foreach ($hookMemoryUsage as $usage)
  293. $totalHookMemoryUsage += $usage;
  294. $globalSize = array();
  295. $totalGlobalSize = 0;
  296. foreach ($GLOBALS as $key => $value)
  297. if ($key != 'GLOBALS')
  298. {
  299. $totalGlobalSize += ($size = $this->sizeofvar($value));
  300. if ($size > 1024)
  301. $globalSize[$key] = round($size / 1024, 1);
  302. }
  303. arsort($globalSize);
  304. $cache = Cache::retrieveAll();
  305. $totalCacheSize = $this->sizeofvar($cache);
  306. echo '
  307. <style>
  308. #ps_profiling{
  309. padding: 20px;
  310. }
  311. .ps_back-office.page-sidebar #ps_profiling{
  312. margin-left: 210px;
  313. }
  314. .ps_back-office.page-sidebar-closed #ps_profiling{
  315. margin-left: 50px;
  316. }
  317. .ps_back-office #ps_profiling{
  318. clear: both;
  319. padding: 10px;
  320. margin-bottom: 50px;
  321. }
  322. #ps_profiling *{
  323. box-sizing:border-box;
  324. -moz-box-sizing:border-box;
  325. color: #888;
  326. }
  327. #ps_profiling .ps_profiling_title{
  328. font-size: 20px;
  329. display: inline-block;
  330. padding-bottom: 15px;
  331. }
  332. #ps_profiling ul{
  333. margin: 0;
  334. padding: 0;
  335. list-style: none;
  336. }
  337. #ps_profiling hr{
  338. margin: 5px 0;
  339. padding: 0;
  340. border: none;
  341. border-bottom: solid 1px #ccc;
  342. }
  343. #ps_profiling td pre{
  344. padding: 6px;
  345. max-width: 600px;
  346. max-height: 140px;
  347. border-radius: 5px;
  348. overflow: auto;
  349. display: block;
  350. color: #777;
  351. font-size: 12px;
  352. line-height: 1.42857;
  353. word-break: break-all;
  354. word-wrap: break-word;
  355. background-color: whitesmoke;
  356. border: 1px solid #cccccc;
  357. }
  358. #ps_profiling table{
  359. width: 100%;
  360. margin-bottom: 10px;
  361. background-color: white;
  362. }
  363. #ps_profiling table th{
  364. font-weight: normal;
  365. border-bottom: 1px solid #999;
  366. color: #888;
  367. padding: 5px 0;
  368. }
  369. #ps_profiling table td{
  370. border-bottom: 1px solid #eee;
  371. padding: 6px;
  372. }
  373. #ps_profiling table .text-right{
  374. text-align: right
  375. }
  376. #ps_profiling table .text-left{
  377. text-align: left
  378. }
  379. #ps_profiling table .text-center{
  380. text-align: center
  381. }
  382. #ps_profiling .ps_profiling_row{
  383. clear: both;
  384. margin-bottom: 60px;
  385. }
  386. #ps_profiling .ps_profiling_col4{
  387. float: left;
  388. padding: 0 10px;
  389. border-right: 1px solid #ccc;
  390. width: 25%;
  391. }
  392. @media (max-width: 1200px) {
  393. #ps_profiling .ps_profiling_col4 {
  394. width: 50%;
  395. }
  396. }
  397. @media (max-width: 600px) {
  398. #ps_profiling .ps_profiling_col4 {
  399. width: 100%;
  400. }
  401. }
  402. #ps_profiling .ps_profiling_col4:last-child{
  403. border-right: none;
  404. }
  405. #ps_profiling .ps_profiling_infobox{
  406. background-color: white;
  407. padding: 5px 10px;
  408. border: 1px solid #ccc;
  409. margin-bottom: 10px;
  410. }
  411. #ps_profiling .text-muted{
  412. color: #bbb;
  413. }
  414. </style>';
  415. echo '
  416. <div id="ps_profiling">
  417. <div class="ps_profiling_row">
  418. <div class="ps_profiling_col4">
  419. <div class="ps_profiling_infobox"><b>Load time</b>: '.$this->displayLoadTimeColor($this->_time['display'] - $start_time, true).'</div>';
  420. if (self::$_footer){
  421. echo '<table>';
  422. echo '<thead><tr><th class="text-left">Execution</th><th class="text-right">Load time (ms)</th></tr><thead><tbody>';
  423. $last_time = $start_time;
  424. foreach ($this->_time as $k => $time)
  425. {
  426. echo '<tr><td>'.$k.'</td><td class="text-right">'.$this->displayLoadTimeColor($time - $last_time).'</td></tr>';
  427. $last_time = $time;
  428. }
  429. echo '</tbody></table>';
  430. }
  431. echo '</div>
  432. <div class="ps_profiling_col4">
  433. <div class="ps_profiling_infobox"><b>Hook processing</b>: '.$this->displayLoadTimeColor($totalHookTime).' ms / '.$this->displayMemoryColor($totalHookMemoryUsage).' Mb<br>
  434. '.(int)count($executedModules).' methods called in '.(int)count(array_unique($executedModules)).' modules</div>';
  435. echo '<table>';
  436. echo '<thead><tr><th class="text-left">Hook</th><th class="text-right">Processing</th></tr><thead><tbody>';
  437. foreach ($hooktime as $hook => $time)
  438. echo '<tr><td>'.$hook.'</td><td class="text-right">'.$this->displayMemoryColor($hookMemoryUsage[$hook]).' Mb in '.$this->displayLoadTimeColor($time).' ms</td></tr>';
  439. echo '</table>
  440. </div>
  441. <div class="ps_profiling_col4">
  442. <div class="ps_profiling_infobox"><b>Memory peak usage</b>: '.$this->displayPeakMemoryColor($memory_peak_usage).' Mb</div>';
  443. if (self::$_footer)
  444. {
  445. echo '<table>';
  446. echo '<thead><tr><th class="text-left">Execution</th><th class="text-right">Memory (Mb)</th><th class="text-right">Total (Mb)</th></tr><thead><tbody>';
  447. $last_memory = 0;
  448. foreach ($this->_memory as $k => $memory)
  449. {
  450. echo '<tr><td>'.$k.'</td><td class="text-right">'.$this->displayMemoryColor($memory - $last_memory).'</td><td class="text-right">'.$this->displayPeakMemoryColor($this->_mempeak[$k]).'</td></tr>';
  451. $last_memory = $memory;
  452. }
  453. echo '<tbody></table>';
  454. }
  455. echo '
  456. </div>';
  457. echo '
  458. <div class="ps_profiling_col4">
  459. <div class="ps_profiling_infobox"><b>Total cache size (in Cache class)</b>: '.$this->displayMemoryColor($totalCacheSize).' Mb</div>
  460. <div class="ps_profiling_infobox"><b>DB type</b>: '.get_class(Db::getInstance()).'</div>
  461. <div class="ps_profiling_infobox"><b>SQL Queries</b>: '.$this->displaySQLQueries(count(Db::getInstance()->queries)).'</div>
  462. <div class="ps_profiling_infobox"><b>Time spent querying</b>: '.$this->displayLoadTimeColor($totalQueryTime).' ms</div>
  463. <div class="ps_profiling_infobox"><b>Included files</b>: '.sizeof(get_included_files()).'</div>
  464. <div class="ps_profiling_infobox"><b>Size of included files</b>: '.$this->displayMemoryColor($totalSize).' Mb</div>
  465. <div class="ps_profiling_infobox"><b>Globals</b> (&gt; 1 Ko only): '.round($totalGlobalSize / 1024).' Ko
  466. <ul>';
  467. foreach ($globalSize as $global => $size)
  468. echo '<li>'.$global.' &asymp; '.$size.' Ko</li>';
  469. echo '</ul></div>
  470. </div>';
  471. $array_queries = array();
  472. $queries = Db::getInstance()->queries;
  473. uasort($queries, 'prestashop_querytime_sort');
  474. foreach ($queries as $data)
  475. {
  476. $query_row = array(
  477. 'time' => $data['time'],
  478. 'query' => $data['query'],
  479. 'location' => $data['stack'][0]['file'].':'.$data['stack'][0]['line'],
  480. 'filesort' => false,
  481. 'rows' => 1,
  482. 'group_by' => false,
  483. 'stack' => $data['stack']
  484. );
  485. if (preg_match('/^\s*select\s+/i', $data['query']))
  486. {
  487. $explain = Db::getInstance()->executeS('explain '.$data['query']);
  488. if (stristr($explain[0]['Extra'], 'filesort'))
  489. $query_row['filesort'] = true;
  490. foreach ($explain as $row)
  491. $query_row['rows'] *= $row['rows'];
  492. if (stristr($data['query'], 'group by') && !preg_match('/(avg|count|min|max|group_concat|sum)\s*\(/i', $data['query']))
  493. $query_row['group_by'] = true;
  494. }
  495. $array_queries[] = $query_row;
  496. }
  497. echo '</div>';
  498. echo '
  499. <div class="ps_profiling_row">
  500. <ul>
  501. <li><a href="#stopwatch">Stopwatch</a></li>
  502. <li><a href="#doubles">Doubles</a></li>
  503. <li><a href="#tables">Tables stress</a></li>
  504. '.(isset(ObjectModel::$debug_list) ? '<li><a href="#objectModels">ObjectModel instances</a></li>' : '').'
  505. <li><a href="#includedFiles">Files included</a></li>
  506. </ul>
  507. </div>
  508. <div class="ps_profiling_row">
  509. <span class="ps_profiling_title"><a name="stopwatch">Stopwatch (with SQL_NO_CACHE) (total = '.count(Db::getInstance()->queries).')</a></span>';
  510. $i = 1;
  511. echo '<table><thead>
  512. <tr>
  513. <th class="text-left">Query</th>
  514. <th class="text-left" width="80px">Time (ms)</th>
  515. <th class="text-left" width="40px">Rows</th>
  516. <th class="text-left" width="70px">Filesort</th>
  517. <th class="text-left" width="70px">Group By</th>
  518. <th class="text-left" width="300px">Location</th>
  519. </tr>
  520. <thead><tbody>';
  521. foreach ($array_queries as $data)
  522. {
  523. $echo_stack = '';
  524. array_shift($data['stack']);
  525. foreach ($data['stack'] as $call)
  526. $echo_stack .= 'from '.str_replace('\\', '/', substr($call['file'], strlen(_PS_ROOT_DIR_))).':'.$call['line'].'<br />';
  527. echo '<tr>';
  528. echo '<td><pre>'.preg_replace("/(^[\s]*)/m", "", htmlspecialchars($data['query'], ENT_NOQUOTES, 'utf-8', false)).'</pre></td>';
  529. echo '<td><span '.$this->getTimeColor($data['time'] * 1000).'>'.round($data['time'] * 1000, 3).'</span></td>';
  530. echo '<td>'.$data['rows'].'</td>';
  531. echo '<td>'.($data['filesort'] ? '<span style="color:green">Yes</span>' : '').'</td>';
  532. echo '<td>'.($data['group_by'] ? '<span style="color:red">Yes</span>' : '').'</td>';
  533. echo '<td>in '.$data['location'].'<br><br><div id="qbt'.($i++).'">'.$echo_stack.'</div></td>';
  534. echo '</tr>';
  535. }
  536. echo '</table>';
  537. $queries = Db::getInstance()->uniqQueries;
  538. arsort($queries);
  539. $count = count(Db::getInstance()->uniqQueries);
  540. foreach ($queries as $q => &$nb)
  541. if ($nb == 1)
  542. $count--;
  543. if ($count)
  544. echo '</div>
  545. <div class="ps_profiling_row">
  546. <span class="ps_profiling_title"><a name="doubles">Doubles (IDs replaced by "XX") (total = '.$count.')</a></span>
  547. <table>';
  548. foreach ($queries as $q => $nb)
  549. if ($nb > 1)
  550. echo '<tr><td><span '.$this->getQueryColor($nb).'>'.$nb.'</span> '.$q.'</td></tr>';
  551. echo '</table></div>
  552. <div class="ps_profiling_row">
  553. <span class="ps_profiling_title"><a name="tables">Tables stress</a></span>
  554. <table>';
  555. $tables = Db::getInstance()->tables;
  556. arsort($tables);
  557. foreach ($tables as $table => $nb)
  558. echo '<tr><td><span '.$this->getTableColor($nb).'>'.$nb.'</span> '.$table.'</td></tr>';
  559. echo '</table></div>';
  560. if (isset(ObjectModel::$debug_list))
  561. {
  562. echo '<div class="ps_profiling_row">
  563. <span class="ps_profiling_title"><a name="objectModels">ObjectModel instances</a></span>';
  564. $list = ObjectModel::$debug_list;
  565. uasort($list, create_function('$a,$b', 'return (count($a) < count($b)) ? 1 : -1;'));
  566. $i = 0;
  567. echo '<table><thead><tr><th class="text-left">Name</th><th class="text-left">Instance</th><th class="text-left">Source</th></tr></thead><tbody>';
  568. foreach ($list as $class => $info)
  569. {
  570. echo '<tr><td>'.$class.'</td>';
  571. echo '<td><span '.$this->getObjectModelColor(count($info)).'>'.count($info).'</span></td>';
  572. echo '<td><div id="object_model_'.$i.'">';
  573. foreach ($info as $trace)
  574. echo ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/').' ['.$trace['line'].']<br />';
  575. echo '</div></td></tr>';
  576. $i++;
  577. }
  578. echo '</tbody></table></div>';
  579. }
  580. // List of included files
  581. echo '<div class="ps_profiling_row">
  582. <span class="ps_profiling_title"><a name="includedFiles">Included files</a></span>
  583. <table>';
  584. $i = 1;
  585. echo '<thead><tr><th class="text-left">#</th><th class="text-left">Filename</th></tr></thead><tbody>';
  586. foreach (get_included_files() as $file)
  587. {
  588. $file = ltrim(str_replace('\\', '/', str_replace(_PS_ROOT_DIR_, '', $file)), '/');
  589. $file = '<span class="text-muted">'.dirname($file).'/</span><span>'.basename($file).'</span>';
  590. echo '<tr><td>'.$i.'</td><td>'.$file.'</td></tr>';
  591. $i++;
  592. }
  593. echo '</tbody></table></div></div>';
  594. }
  595. }
  596. function prestashop_querytime_sort($a, $b)
  597. {
  598. if ($a['time'] == $b['time'])
  599. return 0;
  600. return ($a['time'] > $b['time']) ? -1 : 1;
  601. }