<?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>Jean-Michel Feurprier &#187; OOP</title>
	<atom:link href="http://www.jmfeurprier.com/blog/category/oop/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jmfeurprier.com/blog</link>
	<description>LAMP Web Developer</description>
	<lastBuildDate>Sat, 13 Feb 2010 00:16:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Improving performance with return values caching</title>
		<link>http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/</link>
		<comments>http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 06:26:29 +0000</pubDate>
		<dc:creator>Jean-Michel Feurprier</dc:creator>
				<category><![CDATA[concepts and principles]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tips and tricks]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[profiling]]></category>

		<guid isPermaLink="false">http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/</guid>
		<description><![CDATA[A simple technique to improve a PHP project overall performance.]]></description>
			<content:encoded><![CDATA[<p>Many functions (and methods) in a project will often provide the same return value for the same arguments, like:</p>
<ul>
<li>mathematical functions:</li>
</ul>
<pre class="brush: php">
function SomeMaths($x)
{
	return $x + pow($x, 3.2) - cos($x);
}
</pre>
<ul>
<li>functions which retrieve content from a file:</li>
</ul>
<p><span id="more-38"></span></p>
<pre class="brush: php">
function GetConfiguration()
{
	return parse_ini_file(&#039;configuration.ini&#039;);
}
</pre>
<ul>
<li>functions which retrieve content from a database:</li>
</ul>
<pre class="brush: php">
function GetArticleById($id)
{
	$sqlId  = mysql_real_escape_string($id);
	$result = mysql_query(&quot;SELECT `id`, `title` FROM `article` WHERE `id` = &#039;$sqlId&#039; LIMIT 1&quot;);

	if (FALSE === $result)
	{
		throw new Exception(&#039;Query failed.&#039;);
	}

	return mysql_fetch_assoc($result);
}
</pre>
<p>If your project holds a function like one of these, and:</p>
<ul>
<li>your <a title="Xdebug" href="http://www.xdebug.org/">prefered</a> <a title="KCachegrind" href="http://kcachegrind.sourceforge.net/">profiling</a> <a title="WinCacheGrind" href="http://sourceforge.net/projects/wincachegrind/">tool</a> reveals that a lot of the execution time is spent in this function</li>
<li>its returned value is always the same during a single run (script execution), when providing the same arguments</li>
<li>this function is called more than once per run</li>
</ul>
<p>Then consider caching (saving) its return values.</p>
<p>Here is how it can be achieved (yes, there are <a href="http://memcached.org/">more advanced</a> <a href="http://blog.digitalstruct.com/2008/02/27/php-performance-series-caching-techniques/">techniques</a> to do it, but this is not the point of this post): add a static variable in the body of the function, which will hold an associative array, mapping every parameter combination with a return value:</p>
<pre class="brush: php">
function GetArticleById($id)
{
	static $cache = array();

	// Return value is not in cache yet?
	if (!isset($cache[$id]))
	{
		$sqlId  = mysql_real_escape_string($id);
		$result = mysql_query(&quot;SELECT `id`, `title` FROM `article` WHERE `id` = &#039;$sqlId&#039; LIMIT 1&quot;);

		if (FALSE === $result)
		{
			throw new Exception(&#039;Query failed.&#039;);
		}

		// Add return value to cache
		$cache[$id] = mysql_fetch_assoc($result);
	}

	// Return cache content
	return $cache[$id];
}
</pre>
<p>Here it is, the (possibly heavy) process of querying the database will only be executed once at the first function call. Every other function call with the same argument will use the cached return value.</p>
<p>Keep in mind that the amount of cached return values must be reasonable (available memory is limited). If there are millions of possible arguments combinations for a function in a single run, you&#8217;ll have to consider a more elaborate way of optimizing it (this could be the subject of a future post).</p>
<p>Also, always, <strong>always</strong>, <strong>ALWAYS</strong> profile your code <strong>BEFORE</strong> you decide to apply an optimization like this one (and wait for your project to be nearly completed before profiling).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmfeurprier.com/blog/2009/02/04/improving-performance-with-return-values-caching/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
