<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tom den Braber</title>
    <description>The latest articles on DEV Community by Tom den Braber (@tddenbraber).</description>
    <link>https://dev.to/tddenbraber</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F16147%2F59e47585-a70c-4d1a-9599-1c3a0ea13453.jpg</url>
      <title>DEV Community: Tom den Braber</title>
      <link>https://dev.to/tddenbraber</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tddenbraber"/>
    <language>en</language>
    <item>
      <title>Finding memory issues in PHP programs — Part 2</title>
      <dc:creator>Tom den Braber</dc:creator>
      <pubDate>Thu, 21 Feb 2019 23:00:00 +0000</pubDate>
      <link>https://dev.to/tddenbraber/finding-memory-issues-in-php-programs-part-2-b4i</link>
      <guid>https://dev.to/tddenbraber/finding-memory-issues-in-php-programs-part-2-b4i</guid>
      <description>&lt;h3&gt;
  
  
  Finding memory issues in PHP programs — Part 2
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xf0nPJ9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1000/0%2AAVdDGsKTeEYSw5ig" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xf0nPJ9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1000/0%2AAVdDGsKTeEYSw5ig" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cause of a memory issue is often hard to find. In the &lt;a href="https://www.moxio.com/blog/33/finding-memory-issues-in-php-programs"&gt;previous post&lt;/a&gt;, we looked at two methods for finding the culprits of a memory issue. In case you missed it, check it out!&lt;/p&gt;

&lt;p&gt;In this post, we will look at another tool for finding memory leaks: &lt;a href="https://github.com/arnaud-lb/php-memory-profiler/"&gt;php-memprof&lt;/a&gt;, created by Arnaud Le Blanc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Another profiler… why?
&lt;/h3&gt;

&lt;p&gt;Each profiler has its own characteristics. In the previous post, we saw that the Xdebug profiler generates a ‘cumulative memory profile’: it shows the sum of all the allocations made by a certain function over the lifetime of the program. This makes the generated profile sometimes hard to interpret. With the profiles generated by Xdebug, you cannot see if the memory is already released at the time the profile is generated. However, such a situation could very well indicate a memory leak. php-memprof is made to fill in this gap. It provides information which can be used to find whether a function ‘leaks’ memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up php-memprof
&lt;/h3&gt;

&lt;p&gt;The installation of php-memprof can be done using PECL (pecl install memprof), or manually. After downloading the source, make sure you have &lt;a href="http://judy.sourceforge.net/"&gt;libJudy&lt;/a&gt; installed and run the following commands in the source directory.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;phpize
./configure 
make
make install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Make sure to load the extension (set extension=memprof.so in your php.ini or run your script with php -dextension=memprof.so my_script.php). For my own analyses, I use &lt;a href="https://github.com/tomdenbraber/php-memprof-docker"&gt;a Docker image&lt;/a&gt; that has the extension already installed and loaded by default.&lt;/p&gt;

&lt;p&gt;Note that running Xdebug and php-memprof alongside will not work. To be able to run php-memprof, Xdebug has to be disabled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running example
&lt;/h3&gt;

&lt;p&gt;As our running example, we will use a simple array-based cache implementation. The store function is an excellent example of (valid) code that keeps memory allocated, even after its termination.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArrayBasedCache&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;LogicException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Tried to get '&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;' from cache, but it does not exist. has(&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;key) should be checked first!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Using php-memprof
&lt;/h3&gt;

&lt;p&gt;To signal php-memprof that it should start profiling, the memprof_enable() function has to be called. After the call to this function, php-memprof starts tracking memory allocations. This implies that memory allocated &lt;em&gt;before&lt;/em&gt; memprof_enable() was called will not be taken into account.&lt;/p&gt;

&lt;p&gt;The information that php-memprof gathered can be dumped using one of the following functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;memprof_dump_array() dumps the information in an array format&lt;/li&gt;
&lt;li&gt;memprof_dump_callgrind(resource $stream) dumps the information to the given $stream in the callgrind format, which can be analysed using &lt;a href="https://kcachegrind.github.io/html/Home.html"&gt;KCachegrind&lt;/a&gt; or &lt;a href="https://sourceforge.net/projects/qcachegrindwin/"&gt;qCachegrind&lt;/a&gt; (as shown in the previous post)&lt;/li&gt;
&lt;li&gt;memprof_dump_pprof(resource $stream) dumps the information to the given $stream in the &lt;a href="https://github.com/google/pprof"&gt;pprof&lt;/a&gt; format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s run the following code:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span class="nv"&gt;$cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ArrayBasedCache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;memprof_enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"A:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;memprof_dump_array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;JSON_PRETTY_PRINT&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nv"&gt;$cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"B:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;memprof_dump_array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;JSON_PRETTY_PRINT&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;memprof_disable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The JSON-encoded output of this script is as follows:&lt;/p&gt;

&lt;p&gt;A:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "memory_size": 0,
    "blocks_count": 0,
    "memory_size_inclusive": 0,
    "blocks_count_inclusive": 0,
    "calls": 1,
    "called_functions": []
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;B:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "memory_size": 103,
    "blocks_count": 3,
    "memory_size_inclusive": 479,
    "blocks_count_inclusive": 5,
    "calls": 1,
    "called_functions": {
        "ArrayBasedCache::store": {
            "memory_size": 376,
            "blocks_count": 2,
            "memory_size_inclusive": 376,
            "blocks_count_inclusive": 2,
            "calls": 1,
            "called_functions": []
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first thing to note is that the dumped structure is recursive. The top-level fields indicate the data from the main program, that is the code that is executed outside any function.&lt;br&gt;&lt;br&gt;
In the called_functions field, we can see the callees from the overarching context. For each of these called functions, the same fields are present again.&lt;br&gt;&lt;br&gt;
Let's go over all the fields that we see in the output to find out what they mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;memory_size: the number of bytes allocated from the current context;&lt;/li&gt;
&lt;li&gt;blocks_count: the number of memory blocks allocated from the current context;&lt;/li&gt;
&lt;li&gt;memory_size_inclusive: the number of bytes allocated by the function itself plus all the memory that was allocated by any of the callees of the current context;&lt;/li&gt;
&lt;li&gt;blocks_count_inclusive: same as for memory_size_inclusive, but expressed in blocks;&lt;/li&gt;
&lt;li&gt;calls: the number of times this function was called from the overarching context;&lt;/li&gt;
&lt;li&gt;called_functions: a dictionary with the keys being function-names and the fields being all the fields that are in this table. This field represents the call-stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can see that the A-dump does not contain information about the creation of the ArrayBasedCache itself: this call happened &lt;em&gt;before&lt;/em&gt; the enabling of php-memprof and is therefore not taken into consideration. As the A-dump is generated immediately after enabling php-memprof, we see that the dump has no information about any allocated memory.&lt;br&gt;&lt;br&gt;
The B-dump shows that ArrayBasedCache::store was called once from the 'main' program. We can also see that ArrayBasedCache::store has a memory_size of 376 bytes, eventhough its execution was already terminated by the time the B-dump was generated. These bytes are still in memory because the store method added data to the local $cache field, and did not remove it.&lt;/p&gt;

&lt;p&gt;Let’s see another example:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span class="nv"&gt;$cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ArrayBasedCache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;memprof_enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;memprof_dump_array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;JSON_PRETTY_PRINT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;memprof_disable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and its output:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "memory_size": 103,
    "blocks_count": 3,
    "memory_size_inclusive": 103,
    "blocks_count_inclusive": 3,
    "calls": 1,
    "called_functions": {
        "ArrayBasedCache::store": {
            "memory_size": 0,
            "blocks_count": 0,
            "memory_size_inclusive": 0,
            "blocks_count_inclusive": 0,
            "calls": 1,
            "called_functions": []
        },
        "ArrayBasedCache::clear": {
            "memory_size": 0,
            "blocks_count": 0,
            "memory_size_inclusive": 0,
            "blocks_count_inclusive": 0,
            "calls": 1,
            "called_functions": []
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After calling $cache-&amp;gt;clear(), all items in the cache are removed. The allocation that was done by $cache-&amp;gt;store(...) is thereby deleted, and we can see in the dump that there is indeed no memory allocated by ArrayBasedCache::store at the time the dump is made.&lt;/p&gt;

&lt;p&gt;As you can imagine, the array output will become very large for larger programs. For small, isolated scripts the memory_dump_array works fine. For larger programs, I find it way more useful to look at a visualisation of the output of the memory_dump_callgrind function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;In this post, we looked at another profiler, which approaches memory profiling from a different angle as compared to the Xdebug profiler we looked at last time. This two-part series is meant to help you find the causes of memory issues faster and with a more structured process. Several techniques, like logging memory usage, using profilers, and profile analysis tools have been discussed. Do you miss an important technique that should have been discussed in this series? &lt;a href="http://www.twitter.com/moxio"&gt;Let us know&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/photos/91LGCVN5SAI?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Daan Mooij&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/leak?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://www.moxio.com/blog/36/finding-memory-issues-in-php-programs-part-2"&gt;&lt;em&gt;www.moxio.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on February 21, 2019.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>php</category>
      <category>memoryleak</category>
      <category>profiling</category>
      <category>programming</category>
    </item>
    <item>
      <title>Finding memory issues in PHP programs</title>
      <dc:creator>Tom den Braber</dc:creator>
      <pubDate>Thu, 11 Oct 2018 12:25:12 +0000</pubDate>
      <link>https://dev.to/tddenbraber/finding-memory-issues-in-php-programs-2i50</link>
      <guid>https://dev.to/tddenbraber/finding-memory-issues-in-php-programs-2i50</guid>
      <description>&lt;h1&gt;
  
  
  Finding memory issues in PHP programs
&lt;/h1&gt;

&lt;p&gt;"Fatal error: Allowed memory size of 2097152 bytes exhausted (tried to allocate 528384 bytes)." If this error sounds familiar, this post is for you. The problem with this message is that it does not tell you a lot: it does not tell you where all the memory was allocated. Locating the places where a lot of memory is consumed in large and complex systems is not easy. Luckily, there are some tools available which can help finding the problematic code. In this post, we will cover two methods for finding places in your program where a lot of memory is allocated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running example
&lt;/h2&gt;

&lt;p&gt;We will be using the following code as our running example. The purpose of the code is finding Nemo. There are two functions: one that reads a file in which Nemo could be located, and the other which tries to find a line of which the content is equal to 'nemo'. The problem with this snippet is that it sometimes consumes too much memory. Not always, but with certain files, the program crashes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fetch_data_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;iterable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$resource&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$lines&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$lines&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;finding_nemo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_data_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$filepath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$lines&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$line_number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"nemo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$line_number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//nemo not found&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the techniques and tools described are not needed to solve this issue (can you already spot the problem?), but it enables us to see how those tools and techniques work in practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  memory_get_usage()
&lt;/h3&gt;

&lt;p&gt;PHP has two functions which can tell you something about the memory usage of you program: &lt;code&gt;memory_get_usage&lt;/code&gt; and &lt;code&gt;memory_get_peak_usage&lt;/code&gt;. &lt;br&gt;
&lt;code&gt;memory_get_usage&lt;/code&gt; only gives insight in &lt;em&gt;how much&lt;/em&gt; memory is in use at the moment of the function call. &lt;code&gt;memory_get_peak_usage()&lt;/code&gt; returns the maximum number of bytes allocated by the program until the function call. Both of these functions take one &lt;code&gt;boolean&lt;/code&gt; argument: &lt;code&gt;$real_usage&lt;/code&gt;. If &lt;code&gt;$real_usage&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;memory_get_usage&lt;/code&gt; returns the total amount of memory that is actually allocated from the operating system, but some of it might not (yet) be in use by your program. If it is set to &lt;code&gt;false&lt;/code&gt;, it returns the number of bytes which PHP has requested (and received) from the operating system, and which is actually in use by the program. The following statement always holds: &lt;code&gt;memory_get_usage(true) &amp;gt;= memory_get_usage(false)&lt;/code&gt;.  Memory is requested in blocks, which are not fully used all of the time.&lt;/p&gt;

&lt;p&gt;An advantage of using these functions is that they are really easy to use. One of the possible ways of finding your memory leak is scattering calls to &lt;code&gt;memory_get_usage&lt;/code&gt; all over your code, and logging its output. You can then try to find a pattern: where does the memory usage increase?&lt;br&gt;
A drawback of these functions is that their use is limited, as they do not provide insight in which functions or classes are using all that memory.&lt;/p&gt;

&lt;p&gt;Let's use these functions to get an idea of where our current problem might reside. In the example below, I use marker characters like 'A', 'B', etc. to be able to track a log entry back to a location in the code. Another option is to include &lt;a href="http://php.net/manual/en/language.constants.predefined.php" rel="noopener noreferrer"&gt;'magic constants'&lt;/a&gt; like &lt;code&gt;__FILE__&lt;/code&gt; and &lt;code&gt;__LINE__&lt;/code&gt; in your log output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fetch_data_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;iterable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"A: %d bytes used&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;memory_get_usage&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="cd"&gt;/** original code... **/&lt;/span&gt;
    &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"B: %d bytes used&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;memory_get_usage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$lines&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;finding_nemo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"C: %d bytes used&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;memory_get_usage&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="cd"&gt;/** original code... **/&lt;/span&gt;
    &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"D: %d bytes used&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;memory_get_usage&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//nemo not found&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;finding_nemo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"the_sea.txt"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run our example now, we have the following log output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C: 406912 bytes used
A: 406912 bytes used
B: 3599952 bytes used
D: 3591384 bytes used
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's interesting: until line marker A, there is no problem. Between line A and B, the memory suddenly starts to increase. These markers correspond to the start and end of the &lt;code&gt;fetch_data_from_file&lt;/code&gt; function. Let's try to confirm this hypothesis using another technique.&lt;/p&gt;

&lt;h3&gt;
  
  
  Xdebug profiler
&lt;/h3&gt;

&lt;p&gt;As a PHP programmer, you probably have heard of (and used) Xdebug. If you haven't, check it out and make sure to install it. What you might not know, is that it also comes with a &lt;a href="https://en.wikipedia.org/wiki/Profiling_(computer_programming)" rel="noopener noreferrer"&gt;profiler&lt;/a&gt;: a tool which provides insight in the run time behaviour of a program. This profiler is much more sophisticated than the PHP functions mentioned earlier: instead of giving you just information about how much memory is used, it also provides insight in which functions are actually allocating memory. This is an advantage over the previous technique, because if you don't really have a clue where to look for your memory problem, you will have to scatter a huge amount of calls to &lt;code&gt;memory_get_usage&lt;/code&gt; all over your codebase. Before being able to use the profiler, there are some things that need to be configured in your &lt;code&gt;php.ini&lt;/code&gt;. Note that most of these options cannot be set at run time using &lt;code&gt;ini_set&lt;/code&gt;. &lt;br&gt;
First, you have to enable the profiler.  This can be done in two ways: either by using &lt;code&gt;xdebug.profiler_enable = 1&lt;/code&gt; or by using &lt;code&gt;xdebug.profiler_trigger_enable = 1&lt;/code&gt;. When using the first option, a profile is generated for &lt;em&gt;every&lt;/em&gt; run of your program. The second option only creates a profile of your running program if there is a &lt;code&gt;GET&lt;/code&gt;/&lt;code&gt;POST&lt;/code&gt; variable or &lt;code&gt;COOKIE&lt;/code&gt; set with the name &lt;code&gt;XDEBUG_PROFILER&lt;/code&gt;. You also have to tell Xdebug where it has to store the generated files, using &lt;code&gt;xdebug.profiler_output_dir&lt;/code&gt;. &lt;br&gt;
There are &lt;a href="https://xdebug.org/docs/profiler" rel="noopener noreferrer"&gt;more things&lt;/a&gt; to configure, but with these settings you are already good to go.&lt;/p&gt;

&lt;p&gt;Now, run the script again with the Xdebug profiler enabled. If we look into our configurated output directory, we can find the generated profile there. However, before we can open it, we need another tool: &lt;a href="https://sourceforge.net/projects/qcachegrindwin/" rel="noopener noreferrer"&gt;qCachegrind&lt;/a&gt; for Windows or &lt;a href="https://kcachegrind.github.io/html/Home.html" rel="noopener noreferrer"&gt;kCachegrind&lt;/a&gt; for Linux. I will use qCachegrind for now.&lt;/p&gt;

&lt;p&gt;When opening the profile with qCachegrind you will see something like the picture below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvkj9aj9xdw3zegfwzoq1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvkj9aj9xdw3zegfwzoq1.PNG" alt="qCachgegrind screenshot" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure you select 'Memory' in the dropdown menu at the top of the window, as opposed to 'Time' (this option can be useful if performance is an issue).&lt;br&gt;
When looking at the 'callee map' of the &lt;code&gt;{main}&lt;/code&gt; entry in the function list, you can see by the size of the blocks how the called functions have allocated memory. The larger blocks are the most interesting: these are the functions that allocate the most memory. Each called function is located inside the caller in the callee map.&lt;br&gt;
In the 'Flat Profile' section on the left, you can see a list of functions. For each function, there is an 'Incl.' and a 'Self' column. 'Incl' indicates the amount of memory allocated by this function, including all the memory which is allocated by the callees of that function. 'Self' shows the memory which is allocated by the function itself.&lt;br&gt;
The functions that are most interesting to look at, are those functions that have a relatively high value in the 'Self' column.&lt;br&gt;
As we can see, there are two functions which take up a lot of memory itself: &lt;code&gt;php:fgets&lt;/code&gt; and &lt;code&gt;php:trim&lt;/code&gt;. But wait... &lt;code&gt;trim()&lt;/code&gt; only trims one line at a time, and &lt;code&gt;fgets&lt;/code&gt; only reads one line at a time, right? Why are these functions using so much memory? Here we get at one of the drawbacks of the Xdebug profiler: it generates a 'cumulative memory profile', i.e. when a function is called multiple times, it shows the sum of all the memory that was used over the different times it was called.&lt;/p&gt;

&lt;p&gt;Although the Xdebug profile has its drawbacks, it enables us to see where (potentially) a lot of memory is allocated. We can confirm our hypothesis, namely that the &lt;code&gt;fetch_data_from_file&lt;/code&gt; seems to have a problem, as this function calls two PHP functions which allocate a lot of memory.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fixing the script
&lt;/h2&gt;

&lt;p&gt;Note that a profiler, or logging memory usage, will almost never give you an exact answer of what or where your memory problem is located. Manual analysis will always be part of your debugging process. However, the tools &lt;em&gt;do&lt;/em&gt; help you to build an idea of where the problem might be. At this point, we know which function likely has a problem. Upon closer analysis of the &lt;code&gt;fetch_data_from_file&lt;/code&gt; function, we can see that it uses an array to buffer the complete file. If the file is large, the program will run out of memory. Now we do have enough information to fix it.&lt;br&gt;
Let's work with the assumption that &lt;code&gt;fetch_data_from_file&lt;/code&gt; is also used elsewhere, and that its behaviour should not change. Luckily, there is a solution for this problem: we do not actually have to load the complete file.&lt;/p&gt;

&lt;p&gt;A relatively simple way to work around this problem is to use a &lt;a href="http://php.net/manual/en/language.generators.overview.php" rel="noopener noreferrer"&gt;Generator&lt;/a&gt;. This &lt;a href="https://blog.ircmaxell.com/2012/07/what-generators-can-do-for-you.html" rel="noopener noreferrer"&gt;excellent post&lt;/a&gt; describes the concept in more detail.&lt;/p&gt;

&lt;p&gt;In short, a Generator enables you to write a basic iterator, where you have the control over what information is needed in memory. When looping over an iterator, the loop is in control of when it fetches the next item from the iterator. As the iterator knows how to fetch the next item, it does not neccesarily need to have all items in memory. In this example, this means that there will only be one line of the file in memory at a time.&lt;/p&gt;

&lt;p&gt;Lets look at the example code from above, with a Generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fetch_data_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;iterable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$resource&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;finding_nemo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_data_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$filepath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$lines&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$line_number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"nemo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$line_number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//nemo not found&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly, the &lt;code&gt;finding_nemo&lt;/code&gt; function did not have to change: &lt;code&gt;foreach&lt;/code&gt; loops have no problem with Generators. The &lt;code&gt;fetch_data_from_file&lt;/code&gt; function did change: it now contains the &lt;code&gt;yield&lt;/code&gt; statement. &lt;/p&gt;

&lt;p&gt;When we log the memory usage for this piece of code, we can see that the usage stays low. However, because Xdebug generates a cumulative memory profile, the Xdebug profile will look more or less the same.  This happens because in total, the &lt;code&gt;fetch_data_from_file&lt;/code&gt; function indeed allocates the same amount of memory. However, the function now frees its allocated memory sooner, leading to a memory usage that is overall much lower than in the previous version. This is one of the drawbacks of using the Xdebug profiler. In a follow-up post, I'll show how to use &lt;a href="https://github.com/arnaud-lb/php-memory-profiler/" rel="noopener noreferrer"&gt;php-memory-profiler&lt;/a&gt;, which generates another type of memory profiles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we saw two methods of locating places in your PHP program where a lot of memory is allocated: first, by using PHP's &lt;code&gt;memory_get_usage&lt;/code&gt; function, thereafter by generating a memory profile using Xdebug and analyzing it with qCachegrind. One thing to keep in mind is that there is no tool or technique available which will indefinetely point to the problem. As such, your debugging process will always at least partly consist of manual analysis. In the next post, I'll show how &lt;a href="https://github.com/arnaud-lb/php-memory-profiler/" rel="noopener noreferrer"&gt;php-memory-profiler&lt;/a&gt; can help you find memory leaks in your program.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted at the &lt;a href="https://www.moxio.com/blog/33/" rel="noopener noreferrer"&gt;Moxio company blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>memoryprofiling</category>
      <category>memoryleak</category>
      <category>xdebug</category>
    </item>
    <item>
      <title>The What, Why and How of Type Inference</title>
      <dc:creator>Tom den Braber</dc:creator>
      <pubDate>Sun, 17 Dec 2017 23:00:00 +0000</pubDate>
      <link>https://dev.to/tddenbraber/the-what-why-and-how-of-type-inference-2a3i</link>
      <guid>https://dev.to/tddenbraber/the-what-why-and-how-of-type-inference-2a3i</guid>
      <description>

&lt;p&gt;In &lt;a href="https://www.moxio.com/blog/14/understanding-exceptional-flow"&gt;my previous post&lt;/a&gt; concerning the exceptional flow of PHP programs, I presented a global overview of my project. In this post, I am going to cover one of the building blocks of the algorithm in more depth: type inference. We will discuss what type inference is, why it is needed and how it can be done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait, what?
&lt;/h3&gt;

&lt;p&gt;The words ‘type inference’ might sound scary, but the principle behind it is quite simple. Consider the following code:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Elf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* constructor code */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="cm"&gt;/*... an implementation ...*/&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$what_to_say&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="cm"&gt;/*... also an implementation ... */&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$an_elf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Elf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Legolas"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$an_elf&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"Legolas"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nv"&gt;$an_elf&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"They're taking the hobbits to Isengard!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Looking at this code, we can say a few things. For example, we can say that the expression &lt;code&gt;"Legolas"&lt;/code&gt; is of type &lt;code&gt;string&lt;/code&gt;, because it is text enclosed by quotes. We also know that any occurrence of the &lt;code&gt;$an_elf&lt;/code&gt; variable is of type &lt;code&gt;Elf&lt;/code&gt;, because &lt;code&gt;$an\_elf&lt;/code&gt; is only assigned a value once, namely the expression &lt;code&gt;new Elf("Legolas")&lt;/code&gt; which is of type &lt;code&gt;Elf&lt;/code&gt;. I don't know whether you noticed or not, but... we already inferred a few types. Type inference is nothing else than deducing the types of expressions in a program at &lt;a href="https://en.wikipedia.org/wiki/Compile_time"&gt;Compile Time&lt;/a&gt;, i.e. without actually running the program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iOztURQq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/500/0%2ATGF9qo8PWpjEn180.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iOztURQq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/500/0%2ATGF9qo8PWpjEn180.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  But why?
&lt;/h3&gt;

&lt;p&gt;So why would you want to do this? Well, it is likely that you are already using it, maybe even without knowing it. If you are using an IDE, it probably informs you about the types of expressions and variables. It probably supports ‘click to go to definition’: you click on an expression with type &lt;code&gt;Elf&lt;/code&gt; and your cursor automagically moves to the definition of the &lt;code&gt;Elf&lt;/code&gt; class. You already guessed it: these kind of interactions are possible because of type inference.&lt;/p&gt;

&lt;p&gt;Type inference can also help to spot errors before even running your code. Try to spot the error in the snippet below:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tell_me&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$what_to_tell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* some implementation */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;tell_me&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"where is Gandalf, for I much desire to speak to him"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When your IDE has type inference, it could warn you that you are calling the function &lt;code&gt;tell_me&lt;/code&gt; with an argument of type &lt;code&gt;array&lt;/code&gt;, whereas the definition of the function clearly states that it requires a &lt;code&gt;string&lt;/code&gt;. In this case, it is quite easy to see. But what if these statements were located in different files? When types of expressions are known at compile time, IDEs and static analysis tools can warn programmers that they are making a mistake. Type inference can be a great help while developing. Even better: you are probably already using tools that are powered by type inference algorithms, maybe without even knowing it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Awesome! How can we do this?
&lt;/h3&gt;

&lt;p&gt;When we look back at the process we used to infer types in the first code snippet, we can see that we used two main methods.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We looked at ‘stand-alone’ expressions, like &lt;code&gt;"Legolas"&lt;/code&gt; or &lt;code&gt;new Elf(...)&lt;/code&gt; and inferred the types of those expressions.&lt;/li&gt;
&lt;li&gt;We propagated types of expressions to other expressions. E.g. each occurrence of &lt;code&gt;$an_elf&lt;/code&gt; has type &lt;code&gt;Elf&lt;/code&gt; because it is assigned the expression &lt;code&gt;new Elf(...)&lt;/code&gt; of type &lt;code&gt;Elf&lt;/code&gt; at the start of the program.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The interesting thing is that these methods go hand in hand. For example, if we want to know the type of &lt;code&gt;$an_elf-&amp;gt;getName()&lt;/code&gt;, we have to know the type of &lt;code&gt;$an_elf&lt;/code&gt;: this type needs to be propagated from a definition earlier in the program. The complete expression can be resolved when we know that &lt;code&gt;$an_elf&lt;/code&gt; is of type &lt;code&gt;Elf&lt;/code&gt;, as we can then look at the the definition of &lt;code&gt;Elf::getName()&lt;/code&gt;, which says that this function returns a &lt;code&gt;string&lt;/code&gt;. The type of &lt;code&gt;$an_elf-&amp;gt;getName()&lt;/code&gt; is thus string.&lt;/p&gt;

&lt;p&gt;Implementing a type inference algorithm which uses only infers types on ‘stand-alone’ expressions is not too hard. Combining a simple traversal of the Abstract Syntax Tree (AST) with enough knowledge of the language of a program will do the job. It gets interesting when you also want to propagate the types of expressions to other expressions. In order to do that, we need to know which expressions are dependent on other expressions. We can discern two types of dependences here: control dependence and data dependence. Control dependence says something about the order of execution, whereas data dependences describe which variables influence other variables.&lt;/p&gt;

&lt;p&gt;Control flow data is often represented as a Control Flow Graph (CFG). The nodes in the graph are sets of instructions which are executed linearly, i.e. one after another. The edges represent the ‘jumps’ that might occur in the program. Consider the following snippet.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rand_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a string"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="nx"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The CFG of this snippet looks as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UEYxi36F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/351/0%2APnHL_wW7ChhgMpJS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UEYxi36F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/351/0%2APnHL_wW7ChhgMpJS.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the CFG, we can clearly see that either the if-branch or the else-branch will be executed, but certainly not both in the same run. In the snippet, the variable &lt;code&gt;$a&lt;/code&gt; is used. But what is the type of &lt;code&gt;$a&lt;/code&gt; in this snippet? The correct answer would be that &lt;code&gt;$a&lt;/code&gt; can be a &lt;code&gt;string&lt;/code&gt;, an &lt;code&gt;integer&lt;/code&gt; or a &lt;code&gt;boolean&lt;/code&gt;. However, this is not really useful: although it is true, it does not say a lot. As &lt;code&gt;$a&lt;/code&gt; changes multiple times in the program, it is hard to determine what is meant by the variable &lt;code&gt;$a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But what if we slightly transform the program? We could say, for example, that each variable might be assigned &lt;em&gt;only once&lt;/em&gt;. In this way, we can be sure what the type of the variable is at all times, as it is only initialised but not changed. This form is called the &lt;a href="https://en.wikipedia.org/wiki/Static_single_assignment_form"&gt;Single Static Assignment (SSA) form&lt;/a&gt;. The snippet above would look as follows in SSA:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$a_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rand_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a_1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nv"&gt;$a_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a string"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nv"&gt;$a_3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="nx"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;φ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$a_3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This snippet has exactly the same behaviour as the earlier snippet, but each variable is assigned only once. This makes the process of type inference somewhat easier, as a variable can now have only one type during its entire life. By keeping a link to from the variables in SSA form to the variables in the original program, we can transfer the inferred types back to the original program in non-SSA form. However, translating the program to SSA form only gets you so far. You might have noticed the strange &lt;code&gt;φ&lt;/code&gt; function in the last line of the snippet. The &lt;code&gt;φ&lt;/code&gt; actually tells us that we cannot really know which variable will be used here. The value of &lt;code&gt;φ($a_2, $a_3)&lt;/code&gt; will be either &lt;code&gt;$a_2&lt;/code&gt; &lt;em&gt;or&lt;/em&gt; &lt;code&gt;$a_3&lt;/code&gt;: we know for sure that one of those variables will be used as parameter for &lt;code&gt;some_function&lt;/code&gt;, but we cannot know which one at compile time. The type of the &lt;code&gt;φ&lt;/code&gt;-function is the union of all the types of its parameters. In this example, the type is either a &lt;code&gt;string&lt;/code&gt; (originating from &lt;code&gt;$a_2&lt;/code&gt;) or boolean (originating from &lt;code&gt;$a_3&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;We covered a lot of ground in this post. To summarise, type inference…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is the process of deducing types of expressions at compile time;&lt;/li&gt;
&lt;li&gt;enables all kinds of tools which can be used to help you, the software developer;&lt;/li&gt;
&lt;li&gt;can be done by combining deep knowledge of the programming language and flow information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay tuned for the next post concerning call graph construction!&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools
&lt;/h3&gt;

&lt;p&gt;There are some tools around for creating CFGs and performing type inference. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ircmaxell/php-cfg"&gt;PHP-CFG&lt;/a&gt; — a tool for generating CFGs of PHP programs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ircmaxell/php-types"&gt;PHP-Types&lt;/a&gt; — a tool for performing type inference on CFGs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://www.moxio.com/blog/25/understanding-exceptional-flow-type-inference"&gt;&lt;em&gt;www.moxio.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on December 17,2017.&lt;/em&gt;&lt;/p&gt;





</description>
      <category>typeinference</category>
      <category>staticanalysis</category>
      <category>programming</category>
      <category>php</category>
    </item>
    <item>
      <title>Understanding Exceptional Flow</title>
      <dc:creator>Tom den Braber</dc:creator>
      <pubDate>Wed, 15 Mar 2017 07:00:00 +0000</pubDate>
      <link>https://dev.to/tddenbraber/understanding-exceptional-flow-8jd</link>
      <guid>https://dev.to/tddenbraber/understanding-exceptional-flow-8jd</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A9e-SVkTcV9Vl37Df.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A9e-SVkTcV9Vl37Df.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Maybe you recognise the following situation. You are implementing a new feature, and you know that you can use a certain method, as it already covers some of the functionality you need. You briefly look at it, and you don’t see any exception handling constructs. The method documentation does not contain information about what exceptions can be thrown, for example via a &lt;code&gt;@throws&lt;/code&gt; declaration. You conclude that there is no reason to think any exceptions are thrown or propagated by the method.&lt;br&gt;&lt;br&gt;
 But can you be sure? To come to the conclusion that no exceptions can be thrown or propagated, you would need to trace every method call that could be made by the method you are looking at, and repeat this process for all methods you encounter. You would also need to look up all definitions of internal php functions or methods that are used, to see if they throw any exceptions. This requires an enormous amount of work, and it is tedious to do. It would be very helpful to have this process automated!&lt;/p&gt;

&lt;p&gt;That’s exactly why I am currently working on a tool which models the Exceptional Flow as part of my MSc Thesis Project. In this introductory post, the building blocks of this tool will be discussed briefly. In the posts to follow in this series, each of these building blocks will be covered in more depth.&lt;/p&gt;

&lt;p&gt;The series will conclude with an overview of the results of using the tool on a number of open source projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building blocks
&lt;/h3&gt;

&lt;p&gt;The exception flow model consists of a few building blocks. This is visualised in the picture below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F701%2F1%2AYr24Rf3WghUtvt4fMVQnpg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F701%2F1%2AYr24Rf3WghUtvt4fMVQnpg.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The system takes a complete PHP program as an input. The code is parsed, which results in an &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" rel="noopener noreferrer"&gt;Abstract Syntax Tree (AST)&lt;/a&gt;. This AST serves as the basis for the complete analysis. First, the types will be inferred and mapped back to the AST. Thereafter, the call graph of the program will be created. Using the AST with types and the call graph together, the exception flow can be deduced.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type inference
&lt;/h3&gt;

&lt;p&gt;Because PHP is dynamically typed, the AST does not contain information about the types of expressions. Because these types are needed in order to construct the call graph and to detect which exceptions are thrown, the types of the expressions in the AST need to be inferred. However, before we can do type inference, we need to have a &lt;a href="https://en.wikipedia.org/wiki/Control_flow_graph" rel="noopener noreferrer"&gt;Control Flow Graph (CFG)&lt;/a&gt;, as the paths that can be taken through the code during program execution decide what types a variable can have. Note that a separate CFG is created for each function or method and that these CFGs are not connected by resolving the method and function calls.&lt;/p&gt;

&lt;p&gt;When the CFGs are created, the types can be inferred. These types are mapped back to the AST. At this point, we have an AST which includes type information of expressions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Call graph construction
&lt;/h3&gt;

&lt;p&gt;Because we want to know how exceptions can travel between functions and methods, we want to know for each method which method calls it can make. Because we have done type inference, we can now decide (for most) expressions what type they have. If we encounter a statement like &lt;code&gt;$a-&amp;gt;m()&lt;/code&gt;, and we now the type of &lt;code&gt;$a&lt;/code&gt;, we can limit the number of possible methods this expression resolves to. Polymorphism plays an important role here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inferring the exceptional flow
&lt;/h3&gt;

&lt;p&gt;Now that we have the call graph and the AST with types, we can start inferring the exception flow. The analysis uses the notion of ‘scopes’ and ‘guarded scopes’ &lt;a href="https://www.moxio.com/blog/14/understanding-exceptional-flow#ref_1" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;. A scope in this context is a method or function, whereas a guarded scope is a try/catch/finally block. A guarded scope can be nested in another (guarded) scope.&lt;br&gt;&lt;br&gt;
 An exception that is encountered within a (guarded) scope can originate from four different sources. To start with, the exception can be explicitly thrown using the throw statement. Secondly, the exception can be generated by a statement. This happens when the code causes an exception to occur, without explicitly throwing it. For example, if you call a function which specifies that it returns an int, but actually returns a string, calling this function would result in a TypeError. The third origin of an exception could be a call to a method or function that encounters an exception. The encountered exception is then propagated into the scope of the caller. Finally, an exception can be encountered in a scope, because it was not caught in a nested guarded scope.&lt;br&gt;&lt;br&gt;
 Using these sources, we can model the exceptional flow in a system. The exact algorithm will be covered in a later post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;In this post, all ingredients for building a tool that can model the exceptional flow were briefly discussed.&lt;br&gt;&lt;br&gt;
Stay tuned for the next post in this series, in which the subject of type inference will be covered in more depth.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;[1] Robillard, M. P., &amp;amp; Murphy, G. C. (2003). Static analysis to support the evolution of exception structure in object-oriented systems. ACM Transactions on Software Engineering and Methodology (TOSEM), 12(2), 191–221.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://www.moxio.com/blog/14/understanding-exceptional-flow" rel="noopener noreferrer"&gt;&lt;em&gt;www.moxio.com&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>exceptionflow</category>
      <category>programming</category>
      <category>php</category>
      <category>staticanalysis</category>
    </item>
    <item>
      <title>Query optimization: from a few weeks to 24 hours</title>
      <dc:creator>Tom den Braber</dc:creator>
      <pubDate>Tue, 17 Jan 2017 08:00:00 +0000</pubDate>
      <link>https://dev.to/tddenbraber/query-optimization-from-a-few-weeks-to-24-hours-1a08</link>
      <guid>https://dev.to/tddenbraber/query-optimization-from-a-few-weeks-to-24-hours-1a08</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcbpzhnbq4z94ioypqf6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcbpzhnbq4z94ioypqf6.jpg" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everyone who writes SQL queries encounters them once in a while: those queries that just take too long. Recently, we ran into such an issue with one of our systems. In this blog post, I will first describe the system, then show how the problem could arise and lastly, how we solved it. Spoiler: the process now takes 24 hours… instead of a few weeks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detecting mutations
&lt;/h3&gt;

&lt;p&gt;One of our applications provides our clients with a different view on their own data. Every few weeks, we receive a dataset from the client, which we import into our application. However, the representation that we use in our application differs from the representation of the received data dump. To be able to process the differences between the received dump and the data that is in our system, we use a mutation detector. The mutation detector uses SQL queries to find batches of differences between the data in our application and the received dump. Each batch is first processed before the next batch of changes will be fetched. An example of a mutation detection query can be found below. It detects all entries that do occur in table &lt;code&gt;A&lt;/code&gt; but not in table &lt;code&gt;B&lt;/code&gt;, under the assumption that for an entry which occurs in both &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; it holds that &lt;code&gt;A.id = B.id&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; 
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; 
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; 
    &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; 
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Where to find them
&lt;/h3&gt;

&lt;p&gt;The mutation detector executes the same query over and over again, until no changes can be found. However, MySQL does not keep information about the last query it executed, i.e. MySQL does not know where it already looked for changes. It is very likely that MySQL looks at a record and finds that it isn’t different from the data in our system, because the entry was already covered in a previous query. The result is that the query becomes slower over time: the first changes are detected within milliseconds, but as more changes have been processed, the search for new mutations takes longer and longer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lending MySQL a hand
&lt;/h3&gt;

&lt;p&gt;The solution to this problem is straightforward: we need to give MySQL more information about where it has already looked for changes, so that it does not look at the same entry multiple times. To find out where to start, we run &lt;code&gt;EXPLAIN&lt;/code&gt; to find out how the &lt;code&gt;JOIN&lt;/code&gt; statements are resolved, and which table SQL would read first (we will call this table base from now on). This is the topmost entry in the output of the &lt;code&gt;EXPLAIN&lt;/code&gt; statement. Knowing where MySQL starts searching, we can introduce a "cheap &lt;code&gt;ORDER BY&lt;/code&gt;". Let &lt;code&gt;pk&lt;/code&gt; be the primary key of base; we can add &lt;code&gt;ORDER BY base.pk&lt;/code&gt; &lt;a href="http://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html" rel="noopener noreferrer"&gt;without introducing extra cost&lt;/a&gt;. Now that we have told MySQL in what order it should detect mutations, we can also keep track of where it detected the last one. Instead of querying for &lt;em&gt;just&lt;/em&gt; mutations, we add &lt;code&gt;base.pk&lt;/code&gt; to the selected columns. In the mutation detector, we save the largest value for base.pk that was encountered, and add the following condition to the query: &lt;code&gt;base.pk &amp;gt; [largest base.pk encountered]&lt;/code&gt;. Because of the &lt;code&gt;ORDER BY&lt;/code&gt; and the condition on &lt;code&gt;base.pk&lt;/code&gt;, we are sure that MySQL does not cover the same entry multiple times.&lt;/p&gt;

&lt;p&gt;We can now incorporate these techniques into the mutation detection query given above. Because we do a &lt;code&gt;LEFT JOIN&lt;/code&gt; from &lt;code&gt;A&lt;/code&gt; to &lt;code&gt;B&lt;/code&gt;, we know that &lt;code&gt;A&lt;/code&gt; will be read first and thus corresponds to the base table we talked about earlier. &lt;code&gt;A.id&lt;/code&gt; is the primary key of &lt;code&gt;A&lt;/code&gt; and is already included in &lt;code&gt;A.*&lt;/code&gt;, so in this case, it is not needed to explicitly select &lt;code&gt;A.id&lt;/code&gt;. The resulting query is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; 
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; 
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; 
    &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; 
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;largest&lt;/span&gt; &lt;span class="n"&gt;encountered&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;previous&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; 
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Concluding remarks
&lt;/h3&gt;

&lt;p&gt;This mechanism (including some other small optimizations) reduced the time it took to import a certain dataset from weeks or even months* to 24 hours. The mechanism described above applies to a context where you want to detect and process batches, instead of the complete dataset at once. The key lesson is that adding extra information to a query can gain you a huge speedup. Another thing that each reader should take to heart: use &lt;code&gt;EXPLAIN&lt;/code&gt; to analyze your queries. It will deepen your understanding of how a database handles your query and you will learn how to deal with the database's query strategies.&lt;/p&gt;

&lt;p&gt;*don’t worry, we did not actually wait for weeks: we optimized the query before the process finished.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://www.moxio.com/blog/13/query-optimization-from-a-few-weeks-to-24-hours" rel="noopener noreferrer"&gt;&lt;em&gt;www.moxio.com&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>sql</category>
      <category>optimisation</category>
      <category>database</category>
      <category>explain</category>
    </item>
  </channel>
</rss>
