Added a simple benchmark
authorMarcel Werk <burntime@woltlab.com>
Thu, 24 Nov 2011 15:32:18 +0000 (16:32 +0100)
committerMarcel Werk <burntime@woltlab.com>
Thu, 24 Nov 2011 15:32:18 +0000 (16:32 +0100)
com.woltlab.wcf/coreObject.xml
com.woltlab.wcf/template/footer.tpl
wcfsetup/install/files/lib/system/benchmark/Benchmark.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php

index 9fab9c63ba378a9ccfbae54bb6d4244a631a431b..6f75bc6d4819d1aa7140e25088000ec0d49b376e 100644 (file)
@@ -13,5 +13,8 @@
                <coreobject>
                        <objectname><![CDATA[wcf\system\menu\acp\ACPMenu]]></objectname>
                </coreobject>
+               <coreobject>
+                       <objectname><![CDATA[wcf\system\benchmark\Benchmark]]></objectname>
+               </coreobject>
        </import>
 </data>
index acf43d2c92d5b1073fcb5f71fc953adc9db8c5c6..51ca1ca5a951e59e05efb9ee50a81b9a96fc616a 100644 (file)
                <div>
                        {include file=footerMenu}
                </div>
+               
+               <p style="margin-top: 10px; font-size: .85em" id="benchmark">Execution time: {@$__wcf->getBenchmark()->getExecutionTime()}s ({#($__wcf->getBenchmark()->getExecutionTime()-$__wcf->getBenchmark()->getQueryExecutionTime())/$__wcf->getBenchmark()->getExecutionTime()*100}% PHP, {#$__wcf->getBenchmark()->getQueryExecutionTime()/$__wcf->getBenchmark()->getExecutionTime()*100}% SQL) | SQL queries: {#$__wcf->getBenchmark()->getQueryCount()}</p>
+               
+               <ul id="benchmarkDetails" style="display: none; max-height: 500px; overflow: auto">
+                       {foreach from=$__wcf->getBenchmark()->getItems() item=item}
+                               <li style="margin-bottom: 8px;{if $item.use >= 0.01} color: #b00{/if}">{if $item.type == 1}(SQL Query) {/if}{$item.text}<br /><small style="font-size: .85em">Execution time: {@$item.use}s</small></li>
+                       {/foreach}
+               </ul>
+               
+               <script type="text/javascript">
+                       //<![CDATA[
+                       $(function() {
+                               $('#benchmark').click(function() {
+                                       WCF.showDialog('benchmarkDetails', true);
+                                       return false;
+                               });
+                       });
+                       //]]>
+               </script>
+               
                {event name='copyright'}
        </footer>
        <!-- /FOOTER -->
diff --git a/wcfsetup/install/files/lib/system/benchmark/Benchmark.class.php b/wcfsetup/install/files/lib/system/benchmark/Benchmark.class.php
new file mode 100644 (file)
index 0000000..c9fa902
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+namespace wcf\system\benchmark;
+use wcf\system\SingletonFactory;
+
+/**
+ * Provides functions to do a benchmark.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.benchmark
+ * @category   Community Framework
+ */
+class Benchmark extends SingletonFactory {
+       const TYPE_SQL_QUERY = 1;
+       const TYPE_OTHER = 0;
+       
+       /**
+        * general benchmark start time
+        * @var integer
+        */
+       protected $startTime = 0;
+       
+       /**
+        * benchmark items
+        * @var array
+        */
+       protected $items = array();
+       
+       /**
+        * number of executed sql queries
+        * @var integer
+        */
+       protected $queryCount = 0;
+       
+       /**
+        * total sql query execution time
+        * @var unknown_type
+        */
+       protected $queryTime = 0;
+
+       /**
+        * Creates a new Benchmark object.
+        */
+       protected function init() {
+               $this->startTime = self::getMicrotime();
+       }
+
+       /**
+        * Starts a benchmark.
+        * 
+        * @param       string          $text
+        * @param       integer         $type
+        * @return      integer         index
+        */
+       public function start($text, $type = self::TYPE_OTHER) {
+               $newIndex = count($this->items);
+               $this->items[$newIndex]['text'] = $text;
+               $this->items[$newIndex]['type'] = $type;
+               $this->items[$newIndex]['before'] = self::getMicrotime();
+               $this->items[$newIndex]['start'] = self::compareMicrotimes($this->startTime, $this->items[$newIndex]['before']);
+               return $newIndex;
+       }
+
+       /**
+        * Stops an active benchmark.
+        * 
+        * @param       integer         $index
+        */
+       public function stop($index = null) {
+               if ($index === null) {
+                       $index = count($this->items) - 1;
+               }
+       
+               $this->items[$index]['after'] = self::getMicrotime();
+               $this->items[$index]['use']  = self::compareMicrotimes($this->items[$index]['before'], $this->items[$index]['after']);
+               $this->items[$index]['end'] = self::compareMicrotimes($this->startTime, $this->items[$index]['after']);
+               if ($this->items[$index]['type'] == self::TYPE_SQL_QUERY) {
+                       $this->queryCount++;
+                       $this->queryTime += $this->items[$index]['use'];
+               }
+       }
+
+       /**
+        * Returns the execution time.
+        * 
+        * @return integer
+        */
+       public function getExecutionTime() {
+               return $this->compareMicrotimes($this->startTime, self::getMicrotime());
+       }
+       
+       /**
+        * Returns the sql query execution time
+        * 
+        * @return integer
+        */
+       public function getQueryExecutionTime() {
+               return $this->queryTime;
+       }
+       
+       /**
+        * Returns the number of executed sql queries.
+        * 
+        * @return integer
+        */
+       public function getQueryCount() {
+               return $this->queryCount;
+       }
+       
+       /**
+        * Returns the logged items.
+        * 
+        * @return array
+        */
+       public function getItems() {
+               return $this->items;
+       }
+       
+       /**
+        * Returns the current unix timestamp as a float.
+        * 
+        * @return      float           unix timestamp
+        */
+       protected static function getMicrotime() {
+               return microtime(true);
+       }
+
+       /**
+        * Calculates the difference of two unix timestamps.
+        * 
+        * @param       float           $startTime
+        * @param       float           $endTime
+        * @return      float           difference
+        */
+       protected static function compareMicrotimes($startTime, $endTime) {
+               return round($endTime - $startTime, 4);
+       }
+}
index 4a18ffa8d055d22ccc4ea8ea4c7771ed58f140a5..8d649b1cf1d148e3cf3b4d9744cdf10a8f36c773 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 namespace wcf\system\database\statement;
 use wcf\data\DatabaseObject;
+use wcf\system\benchmark\Benchmark;
 use wcf\system\database\Database;
 use wcf\system\database\DatabaseException;
 
@@ -78,8 +79,14 @@ class PreparedStatement {
                $this->database->incrementQueryCount();
                
                try {
-                       if (!count($parameters)) return $this->pdoStatement->execute();
-                       return $this->pdoStatement->execute($parameters);
+                       Benchmark::getInstance()->start($this->query, Benchmark::TYPE_SQL_QUERY);
+                       
+                       if (!count($parameters)) $result = $this->pdoStatement->execute();
+                       else $result = $this->pdoStatement->execute($parameters);
+                       
+                       Benchmark::getInstance()->stop();
+                       
+                       return $result;
                }
                catch (\PDOException $e) {
                        throw new DatabaseException('Could not execute prepared statement: '.$e->getMessage(), $this->database, $this);