<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://www.tigerheron.com" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>input filters</title>
 <link>http://www.tigerheron.com/category/input-filters</link>
 <description>The taxonomy view with a depth of 0.</description>
 <language>en-US</language>
<item>
 <title>High-performance debugging</title>
 <link>http://www.tigerheron.com/article/2007/09/high-performance-debugging</link>
 <description>&lt;p&gt;
  In this article, I will show you how to use PHP 5 input filters to support
  debug, trace and assert statements so that a one-line change
  disables these statements and restores your script to full production
  performance.
&lt;/p&gt;
&lt;!--break--&gt;

&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;
  The typical debug statement looks like this:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;echo &lt;span class=&quot;str&quot;&gt;&quot;&amp;lt;p&amp;gt;Hello, I am a debug statement&amp;lt;/p&amp;gt;&quot;&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
  This is the workhorse of PHP debugging—at least, when we aren&#039;t
  using a debugger. We insert it as needed and remove it when done.&lt;/p&gt;
&lt;p&gt;
  Sometimes the debug code takes some work to produce or has some
  permanent benefits. The easiest way to preserve it is by placing it
  in a comment:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;// echo &lt;span class=&quot;str&quot;&gt;&quot;&amp;lt;p&amp;gt;Hello, I am a complicated debug statement&amp;lt;/p&amp;gt;&quot;&lt;/span&gt;;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  This can be inconvenient if we  frequently need to enable
  debugging or if we need to enable multiple debug statements. So the
  next variation is to enable debug statements based on a flag:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; ($debugEnabled) echo &lt;span class=&quot;str&quot;&gt;&quot;&amp;lt;p&amp;gt;Hello, I am a debug statement&amp;lt;/p&amp;gt;&quot;&lt;/span&gt;;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  Now, we can turn a number of debug statements on or off with a single
  setting. But we&#039;ve also added some overhead that occurs even when
  the debug statements are disabled. We have also added some extra
  typing that will make us less inclined to use this tool.&lt;/p&gt;
&lt;p&gt;
  You can gain some flexibility by using:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;debug(&lt;span class=&quot;str&quot;&gt;&quot;Hello, I am a debug statement&quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  This opens the door to creating an elaborate debug system, but adds a performance penalty. Not only do we have the overhead of the function call, but the function argument is evaluated each time
  the statement is executed, whether debugging is enabled or not.
  We&#039;re back to:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; ($debugEnabled) debug(&lt;span class=&quot;str&quot;&gt;&quot;Hello, I am a debug statement&quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  PHP provides an&lt;span class=&quot;code&quot;&gt; &lt;a
  href=&quot;http://php.net/manual/en/function.assert.php&quot;&gt;assert()&lt;/a&gt;&lt;/span&gt;
  function which helps check program logic and can be disabled in
  php.ini. This function could be subverted to serve as the base for a
  debug system, but it appears to function much like the &lt;span
  class=&quot;code&quot;&gt;debug&lt;/span&gt; function above, at least in PHP 5.2.4. &lt;/p&gt;
&lt;p&gt;
  For code that services thousands of requests per hour, the small
  overhead of these debug statements is significant and they are
  rarely left in place.&lt;/p&gt;

&lt;h2&gt;Why use debug statements?&lt;/h2&gt;
&lt;p&gt;Before going further, I need to answer the obvious question: why not use debuggers, profilers or other tools instead of debug statements? &lt;/p&gt;
&lt;p&gt;The answer is that it&#039;s not an either-or; each tool has its place. Debug statements are sometimes faster to use or provide information that is easier to understand. For example, the ability to easily  trace all  database queries and send the output to a log file might be more effective in resolving some problems than stepping through the code with a debugger. &lt;/p&gt;
&lt;p&gt;
  The debug system I will present to you has these goals:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;It should support debug, trace and assert statements.&lt;/li&gt;
  &lt;li&gt;It should be easily and completely disabled for production code.&lt;/li&gt;
  &lt;li&gt;It should be easy to enter debug statements. &lt;/li&gt;
  &lt;/ul&gt;

&lt;h2&gt;Setting the stage&lt;/h2&gt;
&lt;p&gt;
  Let me start with the three simple debugging classes I will use in
  this article. Each class name is prefixed with &quot;th&quot; for &quot;Tiger
  Heron&quot;.&lt;/p&gt;
&lt;p&gt;
  The first is the &lt;span class=&quot;code&quot;&gt;thDebug &lt;/span&gt;class, which
  allows us to format the output appropriately for Web or CLI use:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; thDebug
{
    static public function debug($msg)
    {
        &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (php_sapi_name() == &lt;span class=&quot;str&quot;&gt;&#039;cli&#039;&lt;/span&gt;) echo $msg . &lt;span class=&quot;str&quot;&gt;&quot;n&quot;&lt;/span&gt;;
        &lt;span class=&quot;kwrd&quot;&gt;else&lt;/span&gt; echo &lt;span class=&quot;str&quot;&gt;&#039;&amp;lt;p&amp;gt;&#039;&lt;/span&gt; . nl2br($msg) . &lt;span class=&quot;str&quot;&gt;&#039;&amp;lt;/p&amp;gt;&#039;&lt;/span&gt;;
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  The second class is thTrace. Tracing can be enabled or disabled, and
  you can set a threshold for the level of messages that are
  displayed.&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; thTrace
{
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; $isEnabled = &lt;span class=&quot;kwrd&quot;&gt;false&lt;/span&gt;;
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; $level = 0;

    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function enable($isEnabled) { self::$isEnabled = $isEnabled; }
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function isEnabled() { &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; self::$isEnabled; }
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function setLevel($level) { self::$level = $level; }

    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function trace($msg, $level = 0)
    {
        &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (self::$isEnabled &amp;amp;&amp;amp; $level &amp;lt;= self::$level) {
            thDebug::debug($msg);
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  The  final debug class is thAssert, which generates an message only
  if an assertion fails. The &quot;precondition&quot; and &quot;postcondition&quot;
  methods are aliases for assert. Assertions, like tracing, can be enabled or disabled at run-time. &lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; thAssert
{
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; $isEnabled = &lt;span class=&quot;kwrd&quot;&gt;false&lt;/span&gt;;

    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function enable($isEnabled) { self::$isEnabled = $isEnabled; }
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function isEnabled() { &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; self::$isEnabled; }
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function assert($cond, $file, $line, $title=&lt;span class=&quot;str&quot;&gt;&#039;Assertion&#039;&lt;/span&gt;)
        { &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (!$cond) thDebug::debug(&lt;span class=&quot;str&quot;&gt;&quot;$title failed! $file:$line&quot;&lt;/span&gt;);  }
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function precondition($cond, $file, $line)
       { self::assert($cond, $file, $line, &lt;span class=&quot;str&quot;&gt;&#039;Precondition&#039;&lt;/span&gt;); }
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function postcondition($cond, $file, $line)
      { self::assert($cond, $file, $line, &lt;span class=&quot;str&quot;&gt;&#039;Postcondition&#039;&lt;/span&gt;); }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To enable the entire debug system, we use: &lt;/p&gt;
&lt;div&gt;
 &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; thDebugManager
{
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; $isEnabled = &lt;span class=&quot;kwrd&quot;&gt;false&lt;/span&gt;;
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; $isFilterRegistered = &lt;span class=&quot;kwrd&quot;&gt;false&lt;/span&gt;;

    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function enable($isEnabled)
    {
        &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (!$isFilterRegistered &amp;amp;&amp;amp; $isEnabled) {
            require &lt;span class=&quot;str&quot;&gt;&#039;thDebugFilter.inc&#039;&lt;/span&gt;;
            $isFilterRegistered = &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;;
        }
        self::$isEnabled = $isEnabled;
    }

    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function isEnabled() { &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; self::$isEnabled; }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The references to the filter are explained in the next section. It might seem to make more sense to place this code in the thDebug class, but we want to avoid loading any debug-related classes when they are not used. The &lt;span class=&quot;code&quot;&gt;thDebugManager&lt;/span&gt; contains the minimum amount of code that we must load all the time.&lt;/p&gt;
&lt;h2&gt;PHP input filters&lt;/h2&gt;
&lt;p&gt;
  We&#039;ll now introduce the key PHP 5 feature we&#039;ll use for our
  solution: the input filter. We will create a filter that will
  transform PHP code as it is loaded, essentially acting as a
  dynamic pre-processor.&lt;/p&gt;
&lt;p&gt;
  I started with some code from Adam Trachtenberg&#039;s book, &lt;em&gt;&lt;a
  href=&quot;http://www.amazon.com/gp/product/0596006365?ie=UTF8&amp;amp;tag=tigerheron-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596006365&quot;&gt;Upgrading
  to PHP 5&lt;/a&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; alt=&quot;&quot;
  src=&quot;http://www.assoc-amazon.com/e/ir?t=tigerheron-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0596006365&quot;
  border=&quot;0&quot;&gt;&lt;/em&gt;, and tweaked it a bit to create a reusable abstract
  class. To create a new filter, simply subclass this class and
  implement the missing function.&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; thAbstractStreamFilter
    extends php_user_filter
{
    &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; $data;
    &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; $bucket;

    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function onCreate()
    {
        $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data = &lt;span class=&quot;str&quot;&gt;&#039;&#039;&lt;/span&gt;;
        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;;
    }

    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function filter($&lt;span class=&quot;kwrd&quot;&gt;in&lt;/span&gt;, $&lt;span class=&quot;kwrd&quot;&gt;out&lt;/span&gt;, &amp;amp;$consumed, $closing)
    {
        &lt;span class=&quot;kwrd&quot;&gt;while&lt;/span&gt; ($bucket = stream_bucket_make_writeable($&lt;span class=&quot;kwrd&quot;&gt;in&lt;/span&gt;)) {
            $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data .= $bucket-&amp;gt;data;
            $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;bucket = $bucket;
            $consumed = 0;
        }

        $consumed += strlen($&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data);
        $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data = $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;filterData($&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data);
        $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;bucket-&amp;gt;data = $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data;
        $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;bucket-&amp;gt;datalen = strlen($&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data);
        stream_bucket_append($&lt;span class=&quot;kwrd&quot;&gt;out&lt;/span&gt;, $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;bucket);
        $&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;-&amp;gt;data = &lt;span class=&quot;str&quot;&gt;&#039;&#039;&lt;/span&gt;;
        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; PSFS_PASS_ON;
    }

    &lt;span class=&quot;kwrd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function filterData($data);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  I&#039;ll refer you to Adam&#039;s book for the details on input filters.&lt;/p&gt;

&lt;h2&gt;The Debug filter&lt;/h2&gt;
&lt;p&gt;
  Using the &lt;span class=&quot;code&quot;&gt;thAbstractStreamFilter &lt;/span&gt;class, I
  can finally create the core of my debug solution, the &lt;span
  class=&quot;code&quot;&gt;thDebugFilter&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; thDebugFilter
    extends thAbstractStreamFilter
{
    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function filterData($data)
    {
        $data =
            preg_replace(
                &lt;span class=&quot;str&quot;&gt;&#039;!//CODEs*([^nr]*)!m&#039;&lt;/span&gt;,
                &lt;span class=&quot;str&quot;&gt;&#039;$1&#039;&lt;/span&gt;, $data);
        $data =
            preg_replace(
                &lt;span class=&quot;str&quot;&gt;&#039;!//DBGs*([^nr]*)!m&#039;&lt;/span&gt;,
                &lt;span class=&quot;str&quot;&gt;&#039;thDebug::debug($1);&#039;&lt;/span&gt;, $data);
        $data =
            preg_replace(
                &lt;span class=&quot;str&quot;&gt;&#039;!//TRACEs*([^nr]*)!m&#039;&lt;/span&gt;,
                &lt;span class=&quot;str&quot;&gt;&#039;if (thTrace::isEnabled()) thTrace::trace($1);&#039;&lt;/span&gt;, $data);
        $data =
            preg_replace(
                &lt;span class=&quot;str&quot;&gt;&#039;!//ASSERTs*([^nr]*)!m&#039;&lt;/span&gt;,
                &lt;span class=&quot;str&quot;&gt;&#039;if (thAssert::isEnabled()) &#039;&lt;/span&gt; .
                &lt;span class=&quot;str&quot;&gt;&#039;thAssert::assert($1, __FILE__, __LINE__);&#039;&lt;/span&gt;, $data);
        $data =
            preg_replace(
                &lt;span class=&quot;str&quot;&gt;&#039;!//PRECONDs*([^nr]*)!m&#039;&lt;/span&gt;,
                &lt;span class=&quot;str&quot;&gt;&#039;if (thAssert::isEnabled()) &#039;&lt;/span&gt; .
                &lt;span class=&quot;str&quot;&gt;&#039;thAssert::precondition($1, __FILE__, __LINE__);&#039;&lt;/span&gt;, $data);
        $data =
            preg_replace(
                &lt;span class=&quot;str&quot;&gt;&#039;!//POSTCONDs*([^nr]*)!m&#039;&lt;/span&gt;,
                &lt;span class=&quot;str&quot;&gt;&#039;if (thAssert::isEnabled()) &#039;&lt;/span&gt; .
                &lt;span class=&quot;str&quot;&gt;&#039;thAssert::postcondition($1, __FILE__, __LINE__);&#039;&lt;/span&gt;, $data);

        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; $data;
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  I&#039;ve introduced some special &amp;quot;keywords&amp;quot; to PHP: &lt;span
  class=&quot;code&quot;&gt;//CODE&lt;/span&gt;, &lt;span class=&quot;code&quot;&gt;//DBG&lt;/span&gt;, &lt;span
  class=&quot;code&quot;&gt;//TRACE&lt;/span&gt;, &lt;span class=&quot;code&quot;&gt;//ASSERT&lt;/span&gt;,
  &lt;span class=&quot;code&quot;&gt;//PRECOND&lt;/span&gt; and &lt;span
  class=&quot;code&quot;&gt;//POSTCOND&lt;/span&gt;. When the filter is not used, these
  all look like PHP comments. When the filter is enabled, each of
  these statements is transformed into live code.&lt;/p&gt;
&lt;p&gt;
  You could do everything  with //&lt;span class=&quot;code&quot;&gt;CODE&lt;/span&gt;. This
  is used to hide or expose any arbitrary line of code. The other
  statements reduce the typing needed to use the debug classes.&lt;/p&gt;
&lt;p&gt;Here are some examples and their translations &lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;rem&quot;&gt;//CODE $x = $x + 10; 
  -&amp;gt; $x = $x + 10;&lt;/span&gt;
&lt;span class=&quot;rem&quot;&gt;//DBG &quot;This is a debug statement.&quot;&lt;/span&gt;
  -&amp;gt; thDebug::debug(&amp;quot;This is a statement.&amp;quot;);
&lt;span class=&quot;rem&quot;&gt;//TRACE &quot;Level 4 message&quot;, 4&lt;/span&gt;
  -&amp;gt; if (thTrace::isEnabled()) thTrace::trace(&amp;quot;Level 4 message&amp;quot;, 4, __FILE__, _LINE__);
&lt;span class=&quot;rem&quot;&gt;//ASSERT $x == 10&lt;/span&gt;
  -&amp;gt; if (thAssert::isEnabled()) thAssert::assert($x == 10, __FILE__, __LINE__);
&lt;span class=&quot;rem&quot;&gt;//PRECOND $data == null&lt;/span&gt;
  -&amp;gt; if (thAssert::isEnabled()) thAssert::precondition($x == 10, __FILE__, __LINE__);
//POSTCOND $data != null
  -&amp;gt; if (thAssert::isEnabled()) thAssert::postcondition($x == 10, __FILE__, __LINE__);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  Before using an input filter, we have to register it. The following
  line does the job:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;stream_filter_register(&lt;span class=&quot;str&quot;&gt;&#039;phpCode.thDebug&#039;&lt;/span&gt;,&lt;span class=&quot;str&quot;&gt;&#039;thDebugFilter&#039;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;

&lt;h2&gt;Tying it all together with __autoload&lt;/h2&gt;
&lt;p&gt;Now that we have the filter, how do we use it? Here is one way: &lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;function thRequire($file)
{
    &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (thDebugManager::isEnabled()) {
        require &lt;span class=&quot;str&quot;&gt;&#039;php://filter/read=phpCode.thDebug/resource=&#039;&lt;/span&gt; . $file;
    }
    &lt;span class=&quot;kwrd&quot;&gt;else&lt;/span&gt; {
        require $file;
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You would call &lt;span class=&quot;code&quot;&gt;thRequire()&lt;/span&gt; in place of any require statement. You would need similar methods for &lt;span class=&quot;code&quot;&gt;require_once&lt;/span&gt;, &lt;span class=&quot;code&quot;&gt;include&lt;/span&gt; and &lt;span class=&quot;code&quot;&gt;include_once&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I prefer using anothe PHP 5 feature, the &lt;span class=&quot;code&quot;&gt;__autoload()&lt;/span&gt; method. It  allows us to
  dispense with most &lt;span class=&quot;code&quot;&gt;include&lt;/span&gt; and &lt;span class=&quot;code&quot;&gt;require&lt;/span&gt; statements, at least for
  classes. When a class is needed but not defined, the  function
  registered with &lt;span class=&quot;code&quot;&gt;__autoload &lt;/span&gt;will be given a
  chance to load the class. Most of my code is objected-oriented, so this works well for me.&lt;/p&gt;
&lt;p&gt;
  Here is the &lt;span class=&quot;code&quot;&gt; &lt;/span&gt;class that that handles class
  loading. For this article, I have deliberately created a very basic autoloader: it assumes that the class name maps to a file with an &amp;quot;inc&amp;quot; extension and exists in the include path. &lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; thAutoload
{
    &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; function load($className)
    {
        &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (thDebugManager::isEnabled()) {
            require
                &lt;span class=&quot;str&quot;&gt;&#039;php://filter/read=phpCode.thDebug/resource=&#039;&lt;/span&gt; .
                $className . &lt;span class=&quot;str&quot;&gt;&#039;.inc&#039;&lt;/span&gt;;
        }
        &lt;span class=&quot;kwrd&quot;&gt;else&lt;/span&gt; {
            require $className . &lt;span class=&quot;str&quot;&gt;&#039;.inc&#039;&lt;/span&gt;;
        }
        return true;
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
  I still need to register my autoload handler with  &lt;span
  class=&quot;code&quot;&gt;__autoload()&lt;/span&gt;, but that would be bad
  style. There&#039;s only room for one &lt;span
  class=&quot;code&quot;&gt;__autoload()&lt;/span&gt; method, so to allow sharing with other packages, I use
  &lt;span class=&quot;code&quot;&gt;spl_autoload_register()&lt;/span&gt; instead:&lt;/p&gt;
&lt;div&gt;
  &lt;pre class=&quot;csharpcode&quot;&gt;spl_autoload_register(array(&lt;span class=&quot;str&quot;&gt;&#039;thAutoload&#039;&lt;/span&gt;, &lt;span class=&quot;str&quot;&gt;&#039;load&#039;&lt;/span&gt;));&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If we were really using other autoloaders, we should also check if the file exists and return false if it doesn&#039;t, so as to give other autoloaders a chance to try loading the class. &lt;/p&gt;
&lt;p&gt;In any case, all the pieces are present and the solution is complete:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;span class=&quot;code&quot;&gt;thAutoload&lt;/span&gt; and &lt;span class=&quot;code&quot;&gt;thDebugManager&lt;/span&gt; must be loaded with a normal &lt;span class=&quot;code&quot;&gt;require&lt;/span&gt; or &lt;span class=&quot;code&quot;&gt;include&lt;/span&gt;. &lt;/li&gt;
  &lt;li&gt;To enable debugging, call &lt;span class=&quot;code&quot;&gt;thDebugManager::enable(true)&lt;/span&gt; before loading any  classes containing debug statements. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;So how well does it perform?&lt;/h2&gt;
&lt;p&gt;
  One way to see if I achieved my goals is to itemize all the overhead
  imposed by the debugging system &lt;em&gt;when it is disabled&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The compiler will have to compile the &lt;span
  class=&quot;code&quot;&gt;thDebugManager &lt;/span&gt;class.&lt;/li&gt;
  &lt;li&gt;The &lt;span class=&quot;code&quot;&gt;thAutoload &lt;/span&gt;class also a small bit of code that is compiled but not used. &lt;/li&gt;
  &lt;li&gt;One &lt;span class=&quot;code&quot;&gt;if&lt;/span&gt; statement and a function call is executed per loaded
  class.&lt;/li&gt;
  &lt;li&gt;The compiler has to discard some extra comment lines.&lt;/li&gt;
  &lt;/ul&gt;
&lt;p&gt;To me, the overhead appears acceptably low. However, for the highest performing scripts, where you count nanoseconds, this is still not good enough. Here are options for increasing performance:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Using &lt;span class=&quot;code&quot;&gt;__autoload()&lt;/span&gt; is slightly slower than direct loads, so the scripts could use &lt;span class=&quot;code&quot;&gt;thRequire()&lt;/span&gt;. &lt;/li&gt;
  &lt;li&gt;The &lt;span class=&quot;code&quot;&gt;thDebugManager&lt;/span&gt; can make the &lt;span class=&quot;code&quot;&gt;$isEnabled&lt;/span&gt; variable public—bad OO style, but it eliminates a function call. &lt;/li&gt;
  &lt;li&gt;Need more speed? Comment out the unused parts of thRequire(). This involves changing a few lines, but it is far easier than commenting out all the debug statements, which is what you would be doing if you used debug statement in the typical fashion.&lt;/li&gt;
  &lt;li&gt;Need even more? Edit all thRequires into straight requires. If we&#039;re talking high-performance scripts, you shouldn&#039;t have very many of these anyway. While this is not very convenient, you can enable a lot of debugging capability with a few edits.&lt;/li&gt;
  &lt;li&gt;Finally, use an opcode cache. This eliminates all compiler overhead. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Getting the code&lt;/h2&gt;
&lt;p&gt;
  I&#039;ve put all the code together in a ZIP file, along with a sample
  sorting class that uses the debugging features and a main program
  that can be run using the command-line version of PHP.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/files/downloads/high-performance-debugging.zip&quot;&gt;Download high-performance-debugging.zip&lt;/a&gt; ( 7KB) &lt;/p&gt;
&lt;h2&gt;Where to go from here&lt;/h2&gt;
&lt;p&gt;
  The ability to trasnform code dynamically opens up a lot of pre-processing
  possibilities: how about running the code through the C pre-processor? Or a macro processor like m4? Or even adding new syntax to the PHP language? I&#039;ll explore some options in later articles.&lt;/p&gt;
&lt;h2&gt;A special request for opcode cache developers &lt;/h2&gt;
&lt;p&gt;The extra filter processing creates  undesirable overhead that could be easily eliminated with an opcode cache, but it is unclear how many opcode caches support input filters. The dynamic nature of input filters make it almost impossible to determine when the cached code needs to be updated (after all, I could create a filter where the generated code would vary depending on the time of day) and this could discourage developers from adding suport.&lt;/p&gt;
&lt;p&gt;I hope instead that the developers will provide some way of enabling this capability with the caveat that the user must manage the cache, either manually or programmatically. Without some caching support, there is a limited future for using this technique in production code. &lt;/p&gt;
</description>
 <comments>http://www.tigerheron.com/article/2007/09/high-performance-debugging#comments</comments>
 <category domain="http://www.tigerheron.com/category/assert">assert</category>
 <category domain="http://www.tigerheron.com/category/autoload">autoload</category>
 <category domain="http://www.tigerheron.com/category/debugging">debugging</category>
 <category domain="http://www.tigerheron.com/category/input-filters">input filters</category>
 <category domain="http://www.tigerheron.com/category/opcode-caches">opcode caches</category>
 <category domain="http://www.tigerheron.com/category/performance">performance</category>
 <category domain="http://www.tigerheron.com/category/php">PHP</category>
 <category domain="http://www.tigerheron.com/category/software-developers">software developers</category>
 <category domain="http://www.tigerheron.com/category/trace">trace</category>
 <pubDate>Mon, 17 Sep 2007 03:14:32 +0000</pubDate>
 <dc:creator>developer</dc:creator>
 <guid isPermaLink="false">88 at http://www.tigerheron.com</guid>
</item>
</channel>
</rss>
