<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LeaseWeb Labs</title>
	<atom:link href="http://www.leaseweblabs.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.leaseweblabs.com</link>
	<description>Leaseweb Labs</description>
	<lastBuildDate>Mon, 13 May 2013 10:02:22 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Symfony2 MSSQL support with pdo_dblib</title>
		<link>http://www.leaseweblabs.com/2013/05/symfony2-mssql-support-with-pdo_dblib/</link>
		<comments>http://www.leaseweblabs.com/2013/05/symfony2-mssql-support-with-pdo_dblib/#comments</comments>
		<pubDate>Fri, 10 May 2013 15:04:19 +0000</pubDate>
		<dc:creator>Razvan Tudorica (Innovation Engineer)</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[pdo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1390</guid>
		<description><![CDATA[We now maintain a library for connecting to a MSSQL database, since we are using it in one of our Symfony2 applications. You can find the code here: https://github.com/LeaseWeb/LswDoctrinePdoDblib If you are trying to use Doctrine 2 (for Symfony 2) to connect to MSSQL server from a Linux machine, you might encounter the same problems [...]]]></description>
				<content:encoded><![CDATA[<p>We now maintain a library for connecting to a MSSQL database, since we are using it in one of our Symfony2 applications. You can find the code here:</p>
<p><a href="https://github.com/LeaseWeb/LswDoctrinePdoDblib">https://github.com/LeaseWeb/LswDoctrinePdoDblib</a></p>
<p>If you are trying to use Doctrine 2 (for Symfony 2) to connect to MSSQL server from a Linux machine, you might encounter the same problems we did. To be able to connect to MSSQL from a Ubuntu Linux server you will have to install &#8220;php5-sybase&#8221; (Sybase / MS SQL Server module for php5).</p>
<pre class="brush: plain; title: ; notranslate">
$ sudo apt-get install freetds-bin php5-sybase
</pre>
<p>Add the following lines to &#8220;/etc/freetds/freetds.conf&#8221;, and make sure you set it to <a href="http://www.freetds.org/userguide/choosingtdsprotocol.htm">talk the right MSSQL protocol</a>. The TDS protocol version should be 8.0 for MSSQL server 2005 and up, which may be <a href="http://www.freetds.org/userguide/tdshistory.htm">confusing</a>. Also replace &#8220;{mssql-server-ip-address}&#8221; with your MSSQL servers IP address (without the brackets).</p>
<pre class="brush: plain; title: ; notranslate">
    [mssql_freetds]
        host = {mssql-server-ip-address}
        port = 1433
        tds version = 8.0
        client charset = UTF-8
        text size = 20971520
</pre>
<p>If you only connect to one server, you can also set the global TDS protocol version to 8.0 like this:</p>
<pre class="brush: plain; title: ; notranslate">
     [global]
         # TDS protocol version
         tds version = 8.0
</pre>
<p>Now test that your freetds is working by using the command line client. You have to replace {username} and {password} with your username and password (without the brackets):</p>
<pre class="brush: plain; title: ; notranslate">
$ tsql -S mssql_freetds -U {username}
Password: {password}
locale is &quot;en_US.UTF-8&quot;
locale charset is &quot;UTF-8&quot;
using default charset &quot;UTF-8&quot;
1&gt; quit
</pre>
<p>If you specify in &#8220;app/config/parameters.ini&#8221; that you want to use the &#8220;pdo_dblib&#8221; driver like this:</p>
<pre class="brush: plain; title: ; notranslate">
database_driver=&quot;pdo_dblib&quot;
</pre>
<p>You will see the error:</p>
<pre class="brush: plain; title: ; notranslate">
[Doctrine\DBAL\DBALException]
The given 'driver' pdo_dblib is unknown, Doctrine currently supports only the following drivers:
pdo_mysql, pdo_sqlite, pdo_pgsql, pdo_oci, oci8, ibm_db2, pdo_ibm, pdo_sqlsrv
</pre>
<p>This is why you should install our <a href="https://github.com/LeaseWeb/LswDoctrinePdoDblib">LswDoctrinePdoDblib</a> bundle, and following the instructions, you should comment out the &#8220;driver&#8221; and add a &#8220;driver_class&#8221; like this:</p>
<pre class="brush: plain; title: ; notranslate">
    # Doctrine Configuration
    doctrine:
        dbal:
            #driver:   %database_driver%
            driver_class:   Lsw\DoctrinePdoDblib\Doctrine\DBAL\Driver\PDODblib\Driver
</pre>
<p>After that you should be able to run this command without any errors:</p>
<pre class="brush: plain; title: ; notranslate">
$ php app/console doctrine:database:create
</pre>
<p>Now do not expect everything to work flawlessly, since MSSQL is not officially supported, and Doctrine is very picky in what it does and does not accept as database structure. However, this should get you started. Post your experience and questions in the comments. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/05/symfony2-mssql-support-with-pdo_dblib/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>7 habits for creating highly effective Symfony bundles</title>
		<link>http://www.leaseweblabs.com/2013/05/7-habits-for-creating-highly-effective-symfony-bundles/</link>
		<comments>http://www.leaseweblabs.com/2013/05/7-habits-for-creating-highly-effective-symfony-bundles/#comments</comments>
		<pubDate>Thu, 02 May 2013 05:53:58 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[7 habits]]></category>
		<category><![CDATA[bundles]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1316</guid>
		<description><![CDATA[This article is about writing Symfony2 bundles and is based on the 7 habit for highly effective people by Stephen R. Covey. Habit 1: Be Proactive Take initiative in life by realizing that your decisions (and how they align with life&#8217;s principles) are the primary determining factor for effectiveness in your life. Take responsibility for your choices [...]]]></description>
				<content:encoded><![CDATA[<p>This article is about writing <a href="http://symfony.com/doc/current/index.html">Symfony2</a> bundles and is based on the <a href="http://en.wikipedia.org/wiki/The_Seven_Habits_of_Highly_Effective_People">7 habit for highly effective people</a> by <a title="Stephen Covey" href="http://en.wikipedia.org/wiki/Stephen_Covey">Stephen R. Covey</a>.</p>
<h3>Habit 1: Be Proactive</h3>
<blockquote><p>Take initiative in life by realizing that your decisions (and how they align with life&#8217;s principles) are the primary determining factor for effectiveness in your life. Take responsibility for your choices and the consequences that follow.</p></blockquote>
<p>If you choose Symfony2, follow the best practices and believes rigorously, also <a href="http://symfony.com/doc/current/index.html">read everything</a> you can about it (and join <a href="http://symfony.meetup.com/">meetups</a>). Choose <a href="http://symfony.com/doc/current/components/dependency_injection/index.html">Symfony DI</a>, choose <a href="http://symfony.com/doc/current/book/security.html">Symfony security</a>, choose <a href="http://symfony.com/doc/current/book/doctrine.html">Doctrine</a>, choose <a href="http://symfony.com/doc/current/book/performance.html">APC</a>, choose <a href="http://symfony.com/doc/current/contributing/code/standards.html">Symfony coding guidelines</a>, (like <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md">PSR-0</a>, <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md">PSR-1</a> and <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md">PSR-2</a> standards) and most important: choose <a href="http://knpbundles.com/">other people&#8217;s bundles</a>. Choosing Symfony&#8217;s best practices can be hard sometimes, because Symfony leaves many choices open and dictates less choices than other frameworks do (e.g. Rails).</p>
<h3>Habit 2: Begin with the End in Mind</h3>
<blockquote><p>Self-discover and clarify your deeply important character values and life goals. Envision the ideal characteristics for each of your various roles and relationships in life. Create a mission statement.</p></blockquote>
<p>What do you want to achieve, set goals, choose technologies and strategies without limiting you to what is available. This seems like a contradiction with the previous one, but I strongly believe you should find a balance: Choose the Symfony solution or someone else&#8217;s bundle (maybe even do a pull request to add any missing functionality) if you can, but do create your own bundle if you need to, do not compromise before you even started. If you have a clear and unique goal, you can craft your bundle to fulfill it.</p>
<h3>Habit 3: Put First Things First</h3>
<blockquote><p>Prioritize, plan, and execute your week&#8217;s tasks based on importance rather than urgency. Evaluate whether your efforts exemplify your desired character values, propel you toward goals, and enrich the roles and relationships that were elaborated in Habit 2.</p></blockquote>
<p>Have the guts to refactor when you need to and believe me: sometimes you need to. Also, make sure you do not accept bug reports unless you really have to. Often enough these are just feature requests that have urgency, but no importance. Following SCRUM, which has the same concept (work in order of importance), is not sufficient to achieve this habit, but may help you and give you a way of measuring progress.</p>
<h3>Habit 4: Think Win-Win</h3>
<blockquote><p>Genuinely strive for mutually beneficial solutions or agreements in your relationships. Value and respect people by understanding a &#8220;win&#8221; for all is ultimately a better long-term resolution than if only one person in the situation had gotten his way.</p></blockquote>
<p>Bundles do not only compete with each other, they also complete each other. Ownership of bundles can drive competition, which motivates, but open source will allow people to copy solutions from each other, which makes sure no effort has ever to be in vain. Even if a bundle is less popular it does not mean it is less important. Maybe it provided important functionality that was merged into the more popular bundle and this makes the author an major contributor.</p>
<h3>Habit 5: Seek First to Understand, Then to be Understood</h3>
<blockquote><p>Use empathic listening to be genuinely influenced by a person, which compels them to reciprocate the listening and take an open mind to being influenced by you. This creates an atmosphere of caring, and positive problem solving.</p></blockquote>
<p>Do not write your own bundle or criticize other people&#8217;s bundles before the understand what the available bundles offer and actually do. After you did that try to contribute in a positive manner, not by criticizing in comments, but by being positive and providing pull requests. But also when being criticized on your bundle, be positive and try to understand what people are actually saying and what their needs are. Negative comments may hold valuable information.</p>
<h3>Habit 6: Synergize</h3>
<blockquote><p>Combine the strengths of people through positive teamwork, so as to achieve goals no one person could have done alone.</p></blockquote>
<p>We can not create bundles alone, so let others help you and do help other people. Whether it is by providing support, contributing code or reporting bugs. All roles matter and all efforts should be appreciated with a positive attitude. I do not pretend to know why the Open Source paradigm works, but I do know it is all about &#8220;synergy&#8221; and that with Open source we can achieve goals that no single person could have achieved alone.</p>
<h3>Habit 7: Sharpen the Saw</h3>
<blockquote><p>Balance and renew your resources, energy, and health to create a sustainable, long-term, effective lifestyle. It primarily emphasizes exercise for physical renewal, prayer (meditation, yoga, etc.) and good reading for mental renewal. It also mentions service to society for spiritual renewal.</p></blockquote>
<p>The most important advice I heard about this point is: to sharpen the saw, be humble and start sawing. The reason for this is that a lack of experience and the <a href="http://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect">Dunning–Kruger effect</a> will make you grossly overestimated your performance and ability. It will make you become a victim of the seductive and destructive <a href="http://en.wikipedia.org/wiki/Not_invented_here">Not-Invented-Here syndrome</a>. Sharpen the saw is about continuous improvement and especially in IT it is important to keep learning new things, because the technology moves fast. So do not hesitate and start creating Symfony2 bundles right now!</p>
<p><a href="https://github.com/LeaseWeb">Check out our open sourced Symfony bundles on Github!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/05/7-habits-for-creating-highly-effective-symfony-bundles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LeaseWeb labs celebrates 7000 visitors per month</title>
		<link>http://www.leaseweblabs.com/2013/04/leaseweb-labs-celebrates-7000-visitors-per-month/</link>
		<comments>http://www.leaseweblabs.com/2013/04/leaseweb-labs-celebrates-7000-visitors-per-month/#comments</comments>
		<pubDate>Fri, 26 Apr 2013 10:19:04 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[blogging]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1376</guid>
		<description><![CDATA[Figure 1: WordPress Count per Day plugin showing the number of visitors and reads of this blog The LeaseWeb labs blog is getting more and more popular every day. This month we had more than 300 reads per day from our 7000 visitors in the month of April. Looking at the previous months we were seeing 6500 [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: center;"><img class="alignnone size-full wp-image-1381" alt="graph" src="http://www.leaseweblabs.com/wp-content/uploads/2013/04/graph.png" width="752" height="129" /><br />
<strong>Figure 1:</strong> <a href="http://wordpress.org/extend/plugins/count-per-day/">WordPress Count per Day plugin</a> showing the number of visitors and reads of this blog</p>
<p>The LeaseWeb labs blog is getting more and more popular every day. This month we had more than 300 reads per day from our 7000 visitors in the month of April. Looking at the previous months we were seeing 6500 visitors in March and 5300 for February.</p>
<p>Please keep visiting our blog and tell us what you would like to write us about in the comments. Also please like us on Facebook, share our links through Twitter and other social media.</p>
<p>Thank you for visiting!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/04/leaseweb-labs-celebrates-7000-visitors-per-month/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stable marriage problem in PHP</title>
		<link>http://www.leaseweblabs.com/2013/04/stable-marriage-problem-in-php/</link>
		<comments>http://www.leaseweblabs.com/2013/04/stable-marriage-problem-in-php/#comments</comments>
		<pubDate>Fri, 19 Apr 2013 10:25:11 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[marriage]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[smp]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1292</guid>
		<description><![CDATA[In computer science there is a problem known as the &#8220;stable marriage problem&#8221; (SMP). It is a very interesting problem that is best described like this: Given n men and n women, where each person has ranked all members of the opposite sex with a unique number between 1 and n in order of preference, [...]]]></description>
				<content:encoded><![CDATA[<p>In computer science there is a problem known as the &#8220;stable marriage problem&#8221; (SMP). It is a very interesting problem that is best described like this:</p>
<blockquote><p>Given <i>n</i> men and <i>n</i> women, where each person has ranked all members of the opposite sex with a unique number between 1 and <i>n</i> in order of preference, marry the men and women together such that there are no two people of opposite sex who would both rather have each other than their current partners. If there are no such people, all the marriages are &#8220;stable&#8221;. &#8211; source: <a href="http://en.wikipedia.org/wiki/Stable_marriage_problem">Wikipedia</a></p></blockquote>
<p>Fortunately, it is already proven that all marriages can be stable, the proof and the algorithm for such stable marriage problems has been implemented in many languages on <a href="http://rosettacode.org/wiki/Stable_marriage_problem" target="_blank">rosettacode.org</a>.</p>
<p>Since this blog is about PHP, and this was the language missing from the implementations, I decided to port the Python implementation. So this one is for you:</p>
<pre class="brush: php; title: ; notranslate">
    $guyprefers = array(
     'abe'  =&gt; array('abi', 'eve', 'cath', 'ivy', 'jan', 'dee', 'fay', 'bea', 'hope', 'gay'),
     'bob'  =&gt; array('cath', 'hope', 'abi', 'dee', 'eve', 'fay', 'bea', 'jan', 'ivy', 'gay'),
     'col'  =&gt; array('hope', 'eve', 'abi', 'dee', 'bea', 'fay', 'ivy', 'gay', 'cath', 'jan'),
     'dan'  =&gt; array('ivy', 'fay', 'dee', 'gay', 'hope', 'eve', 'jan', 'bea', 'cath', 'abi'),
     'ed'   =&gt; array('jan', 'dee', 'bea', 'cath', 'fay', 'eve', 'abi', 'ivy', 'hope', 'gay'),
     'fred' =&gt; array('bea', 'abi', 'dee', 'gay', 'eve', 'ivy', 'cath', 'jan', 'hope', 'fay'),
     'gav'  =&gt; array('gay', 'eve', 'ivy', 'bea', 'cath', 'abi', 'dee', 'hope', 'jan', 'fay'),
     'hal'  =&gt; array('abi', 'eve', 'hope', 'fay', 'ivy', 'cath', 'jan', 'bea', 'gay', 'dee'),
     'ian'  =&gt; array('hope', 'cath', 'dee', 'gay', 'bea', 'abi', 'fay', 'ivy', 'jan', 'eve'),
     'jon'  =&gt; array('abi', 'fay', 'jan', 'gay', 'eve', 'bea', 'dee', 'cath', 'ivy', 'hope'));
    $galprefers = array(
     'abi'  =&gt; array('bob', 'fred', 'jon', 'gav', 'ian', 'abe', 'dan', 'ed', 'col', 'hal'),
     'bea'  =&gt; array('bob', 'abe', 'col', 'fred', 'gav', 'dan', 'ian', 'ed', 'jon', 'hal'),
     'cath' =&gt; array('fred', 'bob', 'ed', 'gav', 'hal', 'col', 'ian', 'abe', 'dan', 'jon'),
     'dee'  =&gt; array('fred', 'jon', 'col', 'abe', 'ian', 'hal', 'gav', 'dan', 'bob', 'ed'),
     'eve'  =&gt; array('jon', 'hal', 'fred', 'dan', 'abe', 'gav', 'col', 'ed', 'ian', 'bob'),
     'fay'  =&gt; array('bob', 'abe', 'ed', 'ian', 'jon', 'dan', 'fred', 'gav', 'col', 'hal'),
     'gay'  =&gt; array('jon', 'gav', 'hal', 'fred', 'bob', 'abe', 'col', 'ed', 'dan', 'ian'),
     'hope' =&gt; array('gav', 'jon', 'bob', 'abe', 'ian', 'dan', 'hal', 'ed', 'col', 'fred'),
     'ivy'  =&gt; array('ian', 'col', 'hal', 'gav', 'fred', 'bob', 'abe', 'ed', 'jon', 'dan'),
     'jan'  =&gt; array('ed', 'hal', 'gav', 'abe', 'bob', 'jon', 'col', 'ian', 'fred', 'dan'));

    function check($engaged)
    {
        global $guyprefers, $galprefers;
        $inverseengaged = array_combine(array_values($engaged),array_keys($engaged));
        foreach ($engaged as $she =&gt; $he)
        {
            $shelikes = $galprefers[$she];
            $shelikesbetter = array_slice($shelikes,0,array_search($he,$shelikes));
            $helikes = $guyprefers[$he];
            $helikesbetter = array_slice($helikes,0,array_search($she,$helikes));

            foreach ($shelikesbetter as $guy)
            {
                $guysgirl = $inverseengaged[$guy];
                $guylikes = $guyprefers[$guy];
                if (array_search($guysgirl,$guylikes) &gt; array_search($she,$guylikes))
                {
                    printf(&quot;%s and %s like each other better than &quot;.
                           &quot;their present partners: %s and %s, respectively\n&quot;,
                           $she, $guy, $he, $guysgirl);
                    return false;
                }
            }
            foreach ($helikesbetter as $gal)
            {
                $girlsguy = $engaged[$gal];
                $gallikes = $galprefers[$gal];
                if (array_search($girlsguy,$gallikes) &gt; array_search($he,$gallikes))
                {
                    printf(&quot;%s and %s like each other better than &quot;.
                           &quot;their present partners: %s and %s, respectively\n&quot;,
                           $he, $gal, $she, $girlsguy);
                    return false;
                }
            }
        }
        return true;
    }

    function matchmaker($engaged)
    {
        global $guyprefers, $galprefers;

        $guys = array_keys($guyprefers);
        sort($guys);
        $gals = array_keys($galprefers);
        sort($gals);

        $guysfree = $guys;
        $engaged  = array();
        $guyprefers2 = json_decode(json_encode($guyprefers),true);
        $galprefers2 = json_decode(json_encode($galprefers),true);

        while (count($guysfree))
        {
            $guy = array_shift($guysfree);
            $guyslist = &amp;$guyprefers2[$guy];
            $gal = array_shift($guyslist);
            $fiance = isset($engaged[$gal])?$engaged[$gal]:false;
            if (!$fiance)
            {
                // She's free
                $engaged[$gal] = $guy;
                printf(&quot;- %s and %s\n&quot;, $guy, $gal);
            }
            else
            {
                // The bounder proposes to an engaged lass!
                $galslist = $galprefers2[$gal];
                if (array_search($fiance,$galslist) &gt; array_search($guy,$galslist))
                {
                    // She prefers new guy
                    $engaged[$gal] = $guy;
                    printf(&quot;- %s dumped %s for %s\n&quot;, $gal, $fiance, $guy);
                    if ($guyprefers2[$fiance])
                    {
                        // Ex has more girls to try
                        $guysfree[] = $fiance;
                    }
                }
                else
                {
                    // She is faithful to old fiance
                    if (count($guyslist))
                    {
                        // Look again
                        $guysfree[] = $guy;
                    }
                }
            }

        }

        return $engaged;
    }

    $engaged  = array();
    print(&quot;Engagements:\n&quot;);
    $engaged = matchmaker($engaged);

    print(&quot;Couples:\n&quot;);
    ksort($engaged);
    foreach ($engaged as $guy =&gt; $gal)
    {
        printf(&quot;- %s is engaged to %s\n&quot;, $guy, $gal);
    }
    $success = check($engaged);
    print(&quot;Engagement stability check &quot;.($success?'PASSED':'FAILED').&quot;\n&quot;);

    print(&quot;Swapping two fiances to introduce an error\n&quot;);
    $gals = array_keys($galprefers);
    ksort($gals);
    list($engaged[$gals[0]], $engaged[$gals[1]]) = array($engaged[$gals[1]], $engaged[$gals[0]]);
    print(&quot;Couples:\n&quot;);
    ksort($engaged);
    foreach ($engaged as $guy =&gt; $gal)
    {
        printf(&quot;- %s is engaged to %s\n&quot;, $guy, $gal);
    }
    print(&quot;Engagement stability check &quot;.(check($engaged)?'PASSED':'FAILED').&quot;\n&quot;);
</pre>
<p>Expected output:</p>
<pre class="brush: plain; title: ; notranslate">
Engagements:
- abe and abi
- bob and cath
- col and hope
- dan and ivy
- ed and jan
- fred and bea
- gav and gay
- hope dumped col for ian
- abi dumped abe for jon
- hal and eve
- col and dee
- ivy dumped dan for abe
- dan and fay
Couples:
- abi is engaged to jon
- bea is engaged to fred
- cath is engaged to bob
- dee is engaged to col
- eve is engaged to hal
- fay is engaged to dan
- gay is engaged to gav
- hope is engaged to ian
- ivy is engaged to abe
- jan is engaged to ed
Engagement stability check PASSED
Swapping two fiances to introduce an error
Couples:
- abi is engaged to fred
- bea is engaged to jon
- cath is engaged to bob
- dee is engaged to col
- eve is engaged to hal
- fay is engaged to dan
- gay is engaged to gav
- hope is engaged to ian
- ivy is engaged to abe
- jan is engaged to ed
fred and bea like each other better than their present partners: abi and jon, respectively
Engagement stability check FAILED
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/04/stable-marriage-problem-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony2 consistent routing</title>
		<link>http://www.leaseweblabs.com/2013/04/symfony2-consistent-routing/</link>
		<comments>http://www.leaseweblabs.com/2013/04/symfony2-consistent-routing/#comments</comments>
		<pubDate>Fri, 12 Apr 2013 06:56:31 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[crud]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1240</guid>
		<description><![CDATA[Software consistency in large teams is very important, because nobody likes whitespace or formatting commits or arguments about on which line brackets should be placed. Fortunately Symfony2 has a nice Standards Document that you can follow. PHP CodeSniffer can be loaded with the Symfony2 coding standard so that everybody can see the violations on the [...]]]></description>
				<content:encoded><![CDATA[<p>Software consistency in large teams is very important, because nobody likes whitespace or formatting commits or arguments about on which line brackets should be placed. Fortunately Symfony2 has a nice <a href="http://symfony.com/doc/current/contributing/code/standards.html">Standards Document</a> that you can follow. <a href="http://stackoverflow.com/questions/982333/how-useful-is-php-codesniffer-code-standards-enforcement-in-general">PHP CodeSniffer</a> can be loaded with <a href="https://github.com/opensky/Symfony2-coding-standard">the Symfony2 coding standard</a> so that everybody can see the violations on the Continuous Integration (CI) server.</p>
<p>Unfortunately Symfony2 is not that strict everywhere. This lack of strictness allows a group of programmers to argue over and mess up a project. One of the discussions could be about naming routes. Symfony1 had <a href="http://symfony.com/legacy/doc/jobeet/1_2/en/05?orm=Propel#chapter_05_default_routes">a really nice option</a> for &#8220;default routing&#8221;, allowing you to specify a single rule called &#8220;default&#8221; that had url: &#8220;/:module/:action/*&#8221;, but unfortunately that feature is not present in Symfony2. In Symfony2 we can either define routes individually or we can generate them using the CRUD generator (see <a href="http://www.leaseweblabs.com/2013/04/symfony2-crud-generator/">my previous post</a>). This is not a bad option as I will show below.</p>
<h2>Naive routing</h2>
<p>Routing to specific actions in controllers in Symfony2 can be put in a &#8220;routing.yml&#8221; file as described in the <a href="http://symfony.com/doc/2.1/book/routing.html">Routing section of the Symfony2 manual</a>.</p>
<pre class="brush: plain; title: ; notranslate">
# app/config/routing.yml
product:
    pattern:   /product/
    defaults:  { _controller: AcmeDemoBundle:Product:index }

product_edit:
    pattern:  /product/edit/{id}
    defaults: { _controller: AcmeDemoBundle:Product:edit }
</pre>
<p>It is easy to understand that this way the file becomes large and unless people agree on a very strict naming policy it needs to be consulted every time you want to make a link from a view or controller to any action.</p>
<h2>CRUD generated routing</h2>
<p>After using the CRUD generator to generate scaffolding for an Entity called &#8220;Product&#8221;,</p>
<pre class="brush: plain; title: ; notranslate">
maurits@pc:~/project$ app/console generate:doctrine:entity --entity=AcmeDemoBundle:Product
...
Configuration format (yml, xml, php, or annotation) [annotation]:
...
maurits@pc:~/project$ app/console generate:doctrine:crud --entity=AcmeDemoBundle:Product
...
Do you want to generate the &quot;write&quot; actions [no]? yes
...
Configuration format (yml, xml, php, or annotation) [annotation]:
...
Routes prefix [/product]:
...
</pre>
<p>I edited my routing to include this rule:</p>
<pre class="brush: plain; title: ; notranslate">
# app/config/routing.yml
demo_bundle:
    resource: &quot;@AcmeDemoBundle/Controller/&quot;
    type: annotation
    prefix: /
</pre>
<p>This is the only routing entry you need per bundle when using (CRUD generated) routing annotation in your controllers. The &#8220;@Route&#8221; and &#8220;@Template&#8221; annotations can be seen below:</p>
<pre class="brush: php; title: ; notranslate">
/**
 * Product Controller
 *
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    /**
     * Lists all Product entities.
     *
     * @Route(&quot;/&quot;, name=&quot;product&quot;)
     * @Template()
     */
    public function indexAction()
    {
        $em = $this-&gt;getDoctrine()-&gt;getManager();
        $entities = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;findAll();
        return array('entities' =&gt; $entities);
    }

    // ...
}
</pre>
<p>Your routes will look like:</p>
<pre class="brush: plain; title: ; notranslate">
maurits@pc:~/project$ app/console router:debug
[router] Current routes
Name                                                   Method Pattern
...                                                    ...    ...
product                                                ANY    /product/
product_show                                           ANY    /product/{id}/show
product_new                                            ANY    /product/new
product_create                                         POST   /product/create
product_edit                                           ANY    /product/{id}/edit
product_update                                         POST   /product/{id}/update
product_delete                                         POST   /product/{id}/delete
</pre>
<h2>Default Routing in Symfony2</h2>
<p>But would it not be prettier when the only routing entry you needed (per bundle) was this one?</p>
<pre class="brush: plain; title: ; notranslate">
# app/config/routing.yml
demo_bundle:
    resource: &quot;@AcmeDemoBundle&quot;
    type: default
    prefix: /
</pre>
<p>And your code would NOT contain &#8220;@Route&#8221; and &#8220;@Template&#8221; annotations and look like:</p>
<pre class="brush: php; title: ; notranslate">
/**
 * Product Controller
 */
class ProductController extends Controller
{
    /**
     * Lists all Product entities.
     */
    public function indexAction()
    {
        $em = $this-&gt;getDoctrine()-&gt;getManager();
        $entities = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;findAll();
        return array('entities' =&gt; $entities);
    }

    // ...
}
</pre>
<p>Your routes could look like this:</p>
<pre class="brush: plain; title: ; notranslate">
maurits@pc:~/project$ app/console router:debug
[router] Current routes
Name                                                   Method Pattern
...                                                    ...    ...
acme_demo.product.index                                ANY    /product/index.{_format}
acme_demo.product.show                                 ANY    /product/show/{id}.{_format}
acme_demo.product.new                                  ANY    /product/new.{_format}
acme_demo.product.edit                                 ANY    /product/edit/{id}.{_format}
acme_demo.product.delete                               ANY    /product/delete/{id}.{_format}
</pre>
<p>To achieve this we needed to combine the &#8220;new&#8221; &amp; &#8220;create&#8221; and &#8220;edit&#8221; &amp; &#8220;update&#8221; actions and also remove<br />
the &#8220;$request&#8221; argument from the &#8220;delete&#8221; action and replace it by a simple &#8220;$request = $this-&gt;getRequest();&#8221; call. So this code:</p>
<pre class="brush: php; title: ; notranslate">
    /**
     * Displays a form to edit an existing Product entity.
     *
     * @Route(&quot;/{id}/edit&quot;, name=&quot;product_edit&quot;)
     * @Template()
     */
    public function editAction($id)
    {
        $em = $this-&gt;getDoctrine()-&gt;getManager();

        $entity = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;find($id);

        if (!$entity) {
            throw $this-&gt;createNotFoundException('Unable to find Product entity.');
        }

        $editForm = $this-&gt;createForm(new ProductType(), $entity);
        $deleteForm = $this-&gt;createDeleteForm($id);

        return array(
            'entity'      =&gt; $entity,
            'edit_form'   =&gt; $editForm-&gt;createView(),
            'delete_form' =&gt; $deleteForm-&gt;createView(),
        );
    }

    /**
     * Edits an existing Product entity.
     *
     * @Route(&quot;/{id}/update&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction(Request $request, $id)
    {
        $em = $this-&gt;getDoctrine()-&gt;getManager();

        $entity = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;find($id);

        if (!$entity) {
            throw $this-&gt;createNotFoundException('Unable to find Product entity.');
        }

        $deleteForm = $this-&gt;createDeleteForm($id);
        $editForm = $this-&gt;createForm(new ProductType(), $entity);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $em-&gt;persist($entity);
            $em-&gt;flush();

            return $this-&gt;redirect($this-&gt;generateUrl('product_edit', array('id' =&gt; $id)));
        }

        return array(
            'entity'      =&gt; $entity,
            'edit_form'   =&gt; $editForm-&gt;createView(),
            'delete_form' =&gt; $deleteForm-&gt;createView(),
        );
    }
</pre>
<p>has to be <del>changed</del> reduced into this:</p>
<pre class="brush: php; title: ; notranslate">
    /**
     * Edits an existing Product entity.
     */
    public function editAction($id)
    {
        $em = $this-&gt;getDoctrine()-&gt;getManager();

        $entity = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;find($id);

        if (!$entity) {
            throw $this-&gt;createNotFoundException('Unable to find Product entity.');
        }

        $editForm = $this-&gt;createForm(new ProductType(), $entity);
        $deleteForm = $this-&gt;createDeleteForm($id);

        $request = $this-&gt;getRequest();
        if ($request-&gt;getMethod() == 'POST') {

            $editForm-&gt;bind($request);

            if ($editForm-&gt;isValid()) {
                $em-&gt;persist($entity);
                $em-&gt;flush();

                return $this-&gt;redirect($this-&gt;generateUrl('edit', array('id' =&gt; $id)));
            }

        }

        return array(
            'entity' =&gt; $entity,
            'edit_form' =&gt; $editForm-&gt;createView(),
            'delete_form' =&gt; $deleteForm-&gt;createView(),
        );
    }
</pre>
<h3>Relative Routing</h3>
<p>As a bonus this bundle allows you to refer relatively to another route, so instead of writing in the view:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Acme/DemoBundle/Resources/views/Product/index.html.twig --&gt;
&lt;a href=&quot;{{ path('acme_demo.product.show', { 'id': entity.id }) }}&quot;&gt;show&lt;/a&gt;
</pre>
<p>You can simply write this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Acme/DemoBundle/Resources/views/Product/index.html.twig --&gt;
&lt;a href=&quot;{{ path('show', { 'id': entity.id }) }}&quot;&gt;show&lt;/a&gt;
</pre>
<p>Or instead of writing this in the controller:</p>
<pre class="brush: php; title: ; notranslate">
$this-&gt;generateUrl('acme_demo.product.show', array('id' =&gt; $id))
</pre>
<p>You can simply write this:</p>
<pre class="brush: php; title: ; notranslate">
$this-&gt;generateUrl('show', array('id' =&gt; $id))
</pre>
<p>Since routes are now expected to be &#8220;{bundle}.{controller}.{action}&#8221; format and the current route is &#8220;acme_demo.product.index&#8221; the undefined route &#8220;show&#8221; can be automatically matched to &#8220;acme_demo.product.show&#8221;. Apart from enforcing consistency this also allows for greater reuse of (parts of) code.</p>
<h3>Get the bundle</h3>
<p>Now quickly go grab a copy of the <a href="https://github.com/LeaseWeb/LswDefaultRoutingBundle">LswDefaultRoutingBundle</a> and enjoy its benefits!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/04/symfony2-consistent-routing/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Symfony2 CRUD generator</title>
		<link>http://www.leaseweblabs.com/2013/04/symfony2-crud-generator/</link>
		<comments>http://www.leaseweblabs.com/2013/04/symfony2-crud-generator/#comments</comments>
		<pubDate>Mon, 08 Apr 2013 08:06:20 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[crud]]></category>
		<category><![CDATA[generator]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1236</guid>
		<description><![CDATA[I have ran into a real hidden gem. A YouTube user called &#8220;goyocode&#8221; has put an excellent series on using the CRUD generator in Symfony2 online. The links are below: 0. How to Generate an Entity in Symfony2 (11:41) http://www.youtube.com/watch?v=0SE09AlJSEI 1. How to Generate a Repository in Symfony2 (1:20) http://www.youtube.com/watch?v=asC9LL4cHrs 2. How to Generate CRUD [...]]]></description>
				<content:encoded><![CDATA[<p>I have ran into a real hidden gem. A YouTube user called &#8220;goyocode&#8221; has put an excellent series on using the CRUD generator in Symfony2 online. The links are below:</p>
<p>0. How to Generate an Entity in Symfony2 (11:41)<br />
<a href="http://www.youtube.com/watch?v=0SE09AlJSEI">http://www.youtube.com/watch?v=0SE09AlJSEI</a></p>
<p>1. How to Generate a Repository in Symfony2 (1:20)<br />
<a href="http://www.youtube.com/watch?v=asC9LL4cHrs">http://www.youtube.com/watch?v=asC9LL4cHrs</a></p>
<p>2. How to Generate CRUD for an Entity in Symfony2 (4:36)<br />
<a href="http://www.youtube.com/watch?v=Jqp781knyPM">http://www.youtube.com/watch?v=Jqp781knyPM</a></p>
<p>3. How to Install and Configure the Sonata Admin Bundle (11:19)<br />
<a href="http://www.youtube.com/watch?v=_ZGRs4Rd94A">http://www.youtube.com/watch?v=_ZGRs4Rd94A</a></p>
<p>4. How to Create a ManyToMany Relationship with Doctrine2 &amp; Symfony2 (27:35)<br />
<a href="http://www.youtube.com/watch?v=akV4D7cq4UQ">http://www.youtube.com/watch?v=akV4D7cq4UQ</a></p>
<p>5. Hack to Update a ManyToMany Relationship Through the Inverse Side in Doctrine2  (4:00)<br />
<a href="http://www.youtube.com/watch?v=kPrgoe3Jrjw">http://www.youtube.com/watch?v=kPrgoe3Jrjw</a></p>
<p>It clearly explains the process of generating applications using the (Doctrine) CRUD generator in video&#8217;s 0,1 and 2. In video 3 the (Sonata) admin generator is explained.  Video 4 and 5 explain the more advanced entity relationships &#8220;ManyToMany&#8221; and &#8220;inversed ManyToMany&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/04/symfony2-crud-generator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic updates in Symfony2</title>
		<link>http://www.leaseweblabs.com/2013/03/automatic-updates-in-symfony2/</link>
		<comments>http://www.leaseweblabs.com/2013/03/automatic-updates-in-symfony2/#comments</comments>
		<pubDate>Wed, 27 Mar 2013 07:12:54 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[automatic update]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[updates]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1214</guid>
		<description><![CDATA[With a lot of pride we present our 7th Symfony2 bundle: LswAutomaticUpdateBundle. You could say we are on a role here, since all these bundles were published in the past 3 months! We are very proud that LswGettextTranslationBundle seems to be installed a lot (588 installs so far) and that LswApiCallerBundle was top trending bundle this month on http://knpbundles.com. Automatic Update Bundle [...]]]></description>
				<content:encoded><![CDATA[<p>With a lot of pride we present our 7th Symfony2 bundle: <a href="https://github.com/LeaseWeb/LswAutomaticUpdateBundle">LswAutomaticUpdateBundle</a>. You could say we are on a role here, since all these bundles were published in the past 3 months! We are very proud that <a href="https://github.com/LeaseWeb/LswGettextTranslationBundle">LswGettextTranslationBundle</a> seems to be installed a lot (588 installs so far) and that <a href="https://github.com/LeaseWeb/LswApiCallerBundle">LswApiCallerBundle</a> was top trending bundle this month on <a href="http://knpbundles.com/">http://knpbundles.com</a>.</p>
<p><img class="alignnone size-full wp-image-1223" alt="automatic_update" src="http://www.leaseweblabs.com/wp-content/uploads/2013/03/automatic_update.png" width="690" height="140" /></p>
<h2>Automatic Update Bundle</h2>
<p>So, what is new? Well, would&#8217;nt it be cool to have a WordPress-style automatic update button? That&#8217;s exactly what we deliver with <a href="https://github.com/LeaseWeb/LswAutomaticUpdateBundle">LswAutomaticUpdateBundle</a>! Whether or not this desirable can be argued about, but if you are after fast and consistent deployments, this might work for you. You get an extra icon in the Web Debug Toolbar indicating how long ago you last ran the Composer &#8216;update&#8217; command. By clicking the icon you get to a panel where you can enter the password to actually execute the upgrade. Before the upgrade is executed the dry-run is executed. Only if all commands succeed, the upgrade button is shown.</p>
<h2><img class="alignnone size-full wp-image-1227" alt="update_step1" src="http://www.leaseweblabs.com/wp-content/uploads/2013/03/update_step1.png" width="465" height="131" /></h2>
<h2>Features</h2>
<p>The bundle does some cool tricks, such as:</p>
<ul>
<li>Showing app/console and composer.phar output in color, thanks to ANSI to HTML support.</li>
<li>Showing days not updated to remind you to keep your software up-to-date.</li>
<li>Listing all requires and installed versions of the packages with their descriptions.</li>
<li>Identifying unstable (dev) packages to encourage you to run stable versions</li>
</ul>
<p>It also has some password based security, so that it can only be invoked by authorized people.</p>
<h2>Pros and Cons</h2>
<p>Maybe system administrators could see this bundle as a stability threat, because it enables quick updating of the code. Also, from a security point of view one could argue that this bundle is not desirable, since the use of &#8216;system()&#8217; calls from PHP to execute shell commands is frowned upon.</p>
<p>On the other hand the bundle encourages frequent updates and use of versioned packages which should enhance security. Also, because this is a single click upgrade, upgrades should not fail because somebody forgot to type a command or makes a mistake in a command.</p>
<h2>Installation</h2>
<p>As always, you can find the bundle on <a href="https://github.com/LeaseWeb/LswAutomaticUpdateBundle">Github</a> and <a href="https://packagist.org/packages/leaseweb/automatic-update-bundle">Packagist</a>. It supports installation using Composer as described in the <a href="https://github.com/LeaseWeb/LswAutomaticUpdateBundle/blob/master/README.md">README</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/03/automatic-updates-in-symfony2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Avoiding the Memcache &#8216;dog pile&#8217; effect</title>
		<link>http://www.leaseweblabs.com/2013/03/avoiding-the-memcache-dog-pile-effect/</link>
		<comments>http://www.leaseweblabs.com/2013/03/avoiding-the-memcache-dog-pile-effect/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 15:44:32 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1174</guid>
		<description><![CDATA[Normally when you use Memcache you will do something like this: Now let us examine a high traffic website case and see how that will work: Your cache is stored for 90 minutes. It takes about 3 second to calculate the cache value and 1 ms second to read from cache the cache value. You [...]]]></description>
				<content:encoded><![CDATA[<p>Normally when you use Memcache you will do something like this:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// get memcache object
$memcache = $this-&gt;get('memcache.default');
// get value from cache
$value = $memcache-&gt;get('key')
// if value is not in cache
if ($value===false) {
 // calculate the value
 $value = $this-&gt;calculateValue();
 // store the value in the cache for 1 hour
 $value = $memcache-&gt;set('key', $value, 3600);
}
// do something with the value
print &quot;value: $value\n&quot;;
</pre>
<p>Now let us examine a high traffic website case and see how that will work:</p>
<p>Your cache is stored for 90 minutes. It takes about 3 second to calculate the cache value and 1 ms second to read from cache the cache value. You have about 5000 requests per second and that the value is cached. You get 5000 requests per second taking about 5000 ms to read the values from cache. You might think that that is not possible since 5000 &gt; 1000, but that depends on the number of worker processes on your web server  Let&#8217;s say it is about 100 workers (under high load) with 75 threads each. Your web requests take about 20 ms each. Whenever the cache invalidates (after 90 minutes), during 3 seconds, there will be 15000 requests getting a cache miss. All the threads getting a miss will start to calculate the cache value (because they don&#8217;t know the other threads are doing the same). This means that during (almost) 3 seconds the server wont answer a single request, but the requests keep coming in. Since each worker has 75 threads (holding 100 x 75 connections), the amount of workers has to go up to be able to process them.</p>
<p>The heavy forking will cause extra CPU usage and the each worker will use extra RAM. This unexpected increase in RAM and CPU is called a <a href="http://en.wikipedia.org/wiki/Cache_stampede">&#8220;cache stampede&#8221; or &#8220;dog-piling&#8221;</a> and is very unwelcome during peek hours on a web service. This problem is also explained in this <a href="http://highscalability.com/blog/2009/8/7/strategy-break-up-the-memcache-dog-pile.html">&#8220;Memcache dog pile&#8221; article</a>. Another good explanation of the problem can be found on github in a <a href="https://github.com/alombarte/SIFO/issues/15#commit-ref-06c8f96">SIFO issues called &#8220;Cache: Avoid the dogpile effect&#8221;</a>.</p>
<p>There is a solution: we serve the old cache entries while calculating the new value and by using an atomic read and write operation we can make sure only one thread will receive a cache miss when the content is invalidated. The algorithm is similar to <a href="http://wiki.nginx.org/HttpProxyModule#proxy_cache_use_stale">Nginx&#8217;s &#8220;proxy_cache_use_stale&#8221; with &#8220;updating&#8221; mechanism</a> and is implemented in <a href="https://github.com/LeaseWeb/LswMemcacheBundle/blob/master/Cache/AntiDogPileMemcache.php">AntiDogPileMemcache class</a> in LswMemcacheBundle.</p>
<p>Below you see a test showing how it is working. Since phpunit does not support forking I had to go PHP native to make it work. First you see how to flush the Memcache from command line and after that you see the output when we run the test.</p>
<pre class="brush: plain; title: ; notranslate">
maurits@pc:~/src/Lsw/MemcacheBundle/Tests/Cache$ telnet 0 11211
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.
flush_all
OK
quit
Connection closed by foreign host.
maurits@pc:~/src/Lsw/MemcacheBundle/Tests/Cache$ php DogPileTest.php
THREAD | SECOND | STATUS
1 |      0 | STALE!
3 |      0 | STALE!
2 |      0 | STALE!
1 |      0 | SET 1363565115
3 |      0 | SET 1363565115
2 |      0 | SET 1363565115
1 |      1 | 1363565115
3 |      1 | 1363565115
2 |      1 | 1363565115
1 |      2 | 1363565115
3 |      2 | 1363565115
2 |      2 | 1363565115
1 |      3 | STALE!
3 |      3 | 1363565115
2 |      3 | 1363565115
1 |      3 | SET 1363565119
2 |      4 | 1363565119
3 |      4 | 1363565119
1 |      4 | 1363565119
2 |      5 | 1363565119
3 |      5 | 1363565119
2 |      6 | 1363565119
3 |      6 | 1363565119
1 |      5 | 1363565119
1 |      6 | 1363565119
3 |      7 | STALE!
2 |      7 | 1363565119
3 |      7 | SET 1363565123
1 |      7 | 1363565123
2 |      8 | 1363565123
3 |      8 | 1363565123
1 |      8 | 1363565123
2 |      9 | 1363565123
1 |      9 | 1363565123
3 |      9 | 1363565123
maurits@pc:~/src/Lsw/MemcacheBundle/Tests/Cache$
</pre>
<p>Before we get to the code of the test and you are going to apply this everywhere, I want to stress the following considerations:</p>
<ul>
<li><span style="line-height: 13px;">ADP might not be needed if you have low amount of hits or when calculating the new value goes relatively fast.</span></li>
<li>ADP might not be needed if you can break up the big calculation into smaller, maybe even with different timeouts for each part.</li>
<li><span style="line-height: 13px;">ADP might get you older data than the invalidation that is specified. Especially when a thread/worker gets &#8220;false&#8221; for &#8220;get&#8221; request, but fails to &#8220;set&#8221; the new calculated value afterwards.</span></li>
<li>ADP &#8220;get&#8221; and ADP &#8220;set&#8221; are more expensive than the normal &#8220;get&#8221; and &#8220;set&#8221;, slowing down all cache hits.</li>
<li>ADP does not guarantee that the dog pile will not occur. Restarting Memcache, flushing data or not enough RAM will also get keys evicted and you will run into the problem anyway.</li>
</ul>
<p>Now this is the code used to run the test:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
namespace Lsw\MemcacheBundle\Tests\Cache;

use Lsw\MemcacheBundle\Cache\AntiDogPileMemcache;

require_once &quot;../../Cache/LoggingMemcacheInterface.php&quot;;
require_once &quot;../../Cache/LoggingMemcache.php&quot;;
require_once &quot;../../Cache/AntiDogPileMemcache.php&quot;;

class DogPileTest //extends \PHPUnit_Framework_TestCase
{
  public function testDogPile()
  {
    for ($t=1; $t&lt;3; $t++) {
      $pid = pcntl_fork();
      if ($pid == -1) {
        die('could not fork');
      }
      if ($pid==0) {
        break;
      }
    }
    $c = 10;
    $m = new AntiDogPileMemcache(false);
    $m-&gt;addServer('localhost', 11211);
    if ($t==1) {
      echo &quot;THREAD | SECOND | STATUS\n&quot;;
    }
    for ($i=0; $i&lt;$c; $i++) {
      sleep(1);
      if (false === ($v = $m-&gt;getAdp('key'))) {
        echo sprintf(&quot;%6s | %6s | %s\n&quot;, $t, $i, &quot;STALE!&quot;);
        sleep(1);
        $v = time();
        $m-&gt;setAdp('key', $v, 2);
        echo sprintf(&quot;%6s | %6s | %s\n&quot;, $t, $i, &quot;SET $v&quot;);
      } else {
        echo sprintf(&quot;%6s | %6s | %s\n&quot;, $t, $i, $v);
      }
    }
    sleep(3);
  }
}

$t = new DogPileTest();
$t-&gt;testDogPile();
</pre>
<p>For further reading on applying memcache I highly recommend <a href="http://www.ibm.com/developerworks/xml/library/os-memcached/index.html">this article from IBM</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/03/avoiding-the-memcache-dog-pile-effect/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Memcache vs Memcached PHP benchmark</title>
		<link>http://www.leaseweblabs.com/2013/03/memcache-vs-memcached-php-benchmark/</link>
		<comments>http://www.leaseweblabs.com/2013/03/memcache-vs-memcached-php-benchmark/#comments</comments>
		<pubDate>Mon, 18 Mar 2013 07:50:02 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1149</guid>
		<description><![CDATA[We are talking about the following two PHP memcache clients. http://www.php.net/manual/en/book.memcache.php (sudo apt-get install php5-memcache) http://www.php.net/manual/en/book.memcached.php (sudo apt-get install php5-memcached) Should you use memcache or memcached? There are some people writing about this: http://code.google.com/p/memcached/wiki/PHPClientComparison http://stackoverflow.com/questions/1442411/using-memcache-vs-memcached-with-php http://serverfault.com/questions/63383/memcache-vs-memcached Memcached 16% faster than Memcache? Nobody seemed to benchmark the two clients to see which one is faster and [...]]]></description>
				<content:encoded><![CDATA[<p>We are talking about the following two PHP memcache clients.</p>
<ul>
<li><a href="http://www.php.net/manual/en/book.memcache.php">http://www.php.net/manual/en/book.memcache.php</a> (sudo apt-get install php5-memcache)</li>
<li><a href="http://www.php.net/manual/en/book.memcached.php">http://www.php.net/manual/en/book.memcached.php</a> (sudo apt-get install php5-memcached)</li>
</ul>
<p>Should you use memcache or memcached? There are some people writing about this:</p>
<ul>
<li><a href="http://code.google.com/p/memcached/wiki/PHPClientComparison">http://code.google.com/p/memcached/wiki/PHPClientComparison</a></li>
<li><a href="http://stackoverflow.com/questions/1442411/using-memcache-vs-memcached-with-php">http://stackoverflow.com/questions/1442411/using-memcache-vs-memcached-with-php</a></li>
<li><a href="http://serverfault.com/questions/63383/memcache-vs-memcached">http://serverfault.com/questions/63383/memcache-vs-memcached</a></li>
</ul>
<h2>Memcached 16% faster than Memcache?</h2>
<p>Nobody seemed to benchmark the two clients to see which one is faster and that is why I did just that. I tested both clients on the same machine with default settings in Ubuntu 12.04 for both the clients and the server. This is the benchmark script I used:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Initialize values: 10000 keys of 20 bytes with 40 bytes of data
$c = 10000;
$values = array();
for ($i=0;$i&lt;$c;$i++) $values[sprintf('%020s',$i)]=sha1($i);
echo &quot;memcache vs memcached: $c keys\n&quot;;
// Memcached
$m = new Memcached();
$m-&gt;addServer('localhost', 11211);
$start = microtime(true);
foreach ($values as $k =&gt; $v) $m-&gt;set($k, $v, 3600);
$time = microtime(true)-$start;
echo &quot;memcached set: $time\n&quot;;
$start = microtime(true);
foreach ($values as $k =&gt; $v) $m-&gt;get($k);
$time = microtime(true)-$start;
echo &quot;memcached get: $time\n&quot;;
// Memcache
$m = new Memcache();
$m-&gt;addServer('localhost', 11211);
$start = microtime(true);
foreach ($values as $k =&gt; $v) $m-&gt;set($k, $v, 0, 3600);
$time = microtime(true)-$start;
echo &quot;memcache set: $time\n&quot;;
$start = microtime(true);
foreach ($values as $k =&gt; $v) $m-&gt;get($k);
$time = microtime(true)-$start;
echo &quot;memcache get: $time\n&quot;;
</pre>
<p>And this is the output:</p>
<pre class="brush: plain; title: ; notranslate">

maurits@maurits-Aspire-X3960:~$ php memcache.php
memcache vs memcached: 10000 keys
memcached set: 0.91661500930786
memcached get: 0.86234307289124
memcache set: 1.0546097755432
memcache get: 1.0519700050354

</pre>
<p>We clearly see that memcached is faster than memcache, but to find out how much faster we have to use xdebug profiling (install with &#8220;sudo apt-get install php5-xdebug&#8221;). We enabled xdebug profiling by setting &#8220;xdebug.profiler_enable = 1&#8243; in &#8220;/etc/php5/conf.d/xdebug.ini&#8221;. After running the php script a &#8220;cachegrind.out&#8221; file is created in the &#8220;/tmp&#8221; directory. KCachegrind (install with &#8220;sudo apt-get install kcachegrind&#8221;) can analyze that file and make pretty graphs:</p>
<p><img alt="memcache_vs_memcached_3" src="http://www.leaseweblabs.com/wp-content/uploads/2013/03/memcache_vs_memcached_3.png" width="694" height="120" /><br />
picture 1: KCachegrind call graph</p>
<p><img class="alignnone size-full wp-image-1154" alt="memcache_vs_memcached_2" src="http://www.leaseweblabs.com/wp-content/uploads/2013/03/memcache_vs_memcached_2.png" width="643" height="186" /><br />
picture 2: KCachegrind callee map</p>
<p><img alt="memcache_vs_memcached" src="http://www.leaseweblabs.com/wp-content/uploads/2013/03/memcache_vs_memcached.png" width="478" height="428" /><br />
picture 3: KCachegrind flat profile</p>
<h3>Conclusion</h3>
<p>The difference is really small, so there are probably better reasons to choose the memcached client over the memcache client <img src='http://www.leaseweblabs.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/03/memcache-vs-memcached-php-benchmark/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Redis bundle for Symfony2</title>
		<link>http://www.leaseweblabs.com/2013/03/redis-bundle-for-symfony2/</link>
		<comments>http://www.leaseweblabs.com/2013/03/redis-bundle-for-symfony2/#comments</comments>
		<pubDate>Thu, 14 Mar 2013 11:44:00 +0000</pubDate>
		<dc:creator>Maurits van der Schee (Innovation Engineer)</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.leaseweblabs.com/?p=1134</guid>
		<description><![CDATA[The  SncRedisBundle integrates Predis and phpredis into your Symfony2 application. &#8220;Redis is an open source, BSD licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.&#8221; &#8211; redis.io At LeaseWeb we developed the LswMemcacheBundle. This is not because we do not like Redis. Maybe Redis serves a different purpose, since it has support for [...]]]></description>
				<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-1144" alt="redis_screenshot" src="http://www.leaseweblabs.com/wp-content/uploads/2013/03/redis_screenshot.png" width="707" height="125" /></p>
<p>The  <a href="https://github.com/snc/SncRedisBundle/blob/master/Resources/doc/index.md">SncRedisBundle</a> integrates <a href="https://github.com/nrk/predis">Predis</a> and <a href="https://github.com/nicolasff/phpredis">phpredis</a> into your Symfony2 application.</p>
<blockquote><p>&#8220;Redis is an open source, BSD licensed, advanced <strong>key-value store</strong>. It is often referred to as a <strong>data structure server</strong> since keys can contain <a href="http://redis.io/topics/data-types#strings">strings</a>, <a href="http://redis.io/topics/data-types#hashes">hashes</a>, <a href="http://redis.io/topics/data-types#lists">lists</a>, <a href="http://redis.io/topics/data-types#sets">sets</a> and <a href="http://redis.io/topics/data-types#sorted-sets">sorted sets</a>.&#8221; &#8211; <a href="http://redis.io/">redis.io</a></p></blockquote>
<p>At LeaseWeb we developed the <a href="https://github.com/LeaseWeb/LswMemcacheBundle">LswMemcacheBundle</a>. This is not because we do not like Redis. Maybe Redis serves a different purpose, since it has support for data structures, but is single threaded on the other hand. Having data structures could lead to better (more efficient) cache usage, while being single threaded does make a difference on the maximum amount of concurrent get and set operations (see <a href="http://dormando.livejournal.com/525147.html">benchmark</a>). So without choosing for either Redis or Memcache we want to tell you about <a href="https://github.com/snc/SncRedisBundle/blob/master/Resources/doc/index.md">SncRedisBundle</a> for Symfony.</p>
<ul>
<li><a href="http://www.slideshare.net/errazudin/rediscover-speed-with-redisand-php">This is an awesome set of slides about Redis</a></li>
<li><a href="http://redis.io/documentation">Redis has very good documentation</a></li>
<li><a href="http://oldblog.antirez.com/post/redis-manifesto.html">It even has a manifesto</a></li>
<li><a href="https://github.com/snc/SncRedisBundle/blob/master/Resources/doc/index.md">The Symfony2 bundle for redis is really good</a></li>
<li><a href="http://redis4you.com/articles.php?id=014&amp;name=redis">If you do high traffic sites be careful not to run into open file limit issues</a></li>
</ul>
<p>The biggest differences between Redis and Memcache we found:</p>
<ul>
<li>Redis has support for data structures</li>
<li>Redis has support for persistent storage</li>
<li>Redis has more features (in general)</li>
<li><span style="line-height: 13px;">php-redis and memcached are both C based clients, but php-redis is not yet in the Ubuntu repository and predis might be slower.</span></li>
<li>Memcache is multi-threaded and gets higher IOPS on a multi core server</li>
</ul>
<p>If you run a high traffic PHP site, consider running Redis and/or Memcache and share your thoughts with us.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leaseweblabs.com/2013/03/redis-bundle-for-symfony2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
