<?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>devel.kostdoktorn.se</title>
	<atom:link href="http://devel.kostdoktorn.se/feed" rel="self" type="application/rss+xml" />
	<link>http://devel.kostdoktorn.se</link>
	<description>Wordpress odds and ends</description>
	<lastBuildDate>Sat, 24 Oct 2009 18:22:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Plugin for simpler performance profiling</title>
		<link>http://devel.kostdoktorn.se/wp-profile-plugin</link>
		<comments>http://devel.kostdoktorn.se/wp-profile-plugin#comments</comments>
		<pubDate>Sat, 24 Oct 2009 18:22:51 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://devel.kostdoktorn.se/?p=44</guid>
		<description><![CDATA[The two areas where performance problems with WordPress plugins are most common are custom filters/actions and database queries. WP-Profile is a plugin that helps you find such problems.
Actions and filters
WordPress has an intricate system of actions and filters which is used all over the place: to convert : ) into  , to make links [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_45" class="wp-caption alignright" style="width: 260px"><img class="size-full wp-image-45 " title="Filters vs the rest" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/profiling-filters1.gif" alt="Filters vs the rest" width="250" height="264" /><p class="wp-caption-text">How time is spent on a compex page</p></div>
<p>The two areas where performance problems with WordPress plugins are most common are custom filters/actions and database queries. WP-Profile is a plugin that helps you find such problems.</p>
<h3>Actions and filters</h3>
<p>WordPress has an intricate system of <a href="http://codex.wordpress.org/Plugin_API/Action_Reference">actions</a> and <a href="http://codex.wordpress.org/Plugin_API/Filter_Reference">filters</a> which is used all over the place: to convert : ) into <img src='http://devel.kostdoktorn.se/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> , to make links clickable and to handle the login procedure are just some examples.</p>
<p>Every action and filter is a hook that allows plugins to call custom functions and easily change or override default behavior. That is very useful.</p>
<p>It also makes it easy to really ruin performance as some common filters are called a hundred times or more for more complex pages, making small inefficiencies add up really quickly.<span id="more-44"></span></p>
<p>Unfortunately there are no good ways to keep track of the performance impact of individual filters. It is possible to profile the whole system using for example <a href="http://xdebug.org/">XDebug</a> and *Cachegrind like I did in an <a href="http://devel.kostdoktorn.se/profiling-wordpress-performance-regression">earlier post</a> but it is a lot of work and often overkill during plugin development.</p>
<h3>Database queries</h3>
<p>Database queries in stock WordPress are highly optimized. So much so that they usually only takes a few percent of total time. It is, however, very easy to change this and even seemingly simple queries can take surprisingly long time. By defining SAVEQUERIES in wp-config.php WordPress will record all queries and how long they took to execute in <code>$wpdb-&gt;queries</code>.</p>
<h3>WP-Profile</h3>
<p>WP-Profile is a small plugin I&#8217;ve written to use when developing plugins and modifying WordPress. It keeps track of all calls to actions/filters and presents it in an accessible fashion together with  query information collected through SAVEQUERIES. <strong>It requires that you are comfortable making minor changes to core WordPress files</strong> to set up. It is for testing only. You can <a href="http://devel.kostdoktorn.se/wp-content/uploads/wp-profile.0.1.zip">download it here</a>.</p>
<p>This is the result on stock WordPress for a rather complex page with a lot of comments. Sort tables by clicking on table header (thanks to <a href="http://tablesorter.com/">JQuery TableSorter</a>):</p>
<link rel='stylesheet' id='wp-profile-css'  href='http://devel.kostdoktorn.se/wp-content/plugins/wp-profile/css/style.css' type='text/css' media='all' />
<script type='text/javascript' src='http://devel.kostdoktorn.se/wp-includes/js/jquery/jquery.js?ver=1.3.2'></script><br />
<script type='text/javascript' src='http://devel.kostdoktorn.se/wp-content/plugins/wp-profile/js/jquery.tablesorter.min.js'></script></p>
<div class="profile"><script type="text/javascript"> jQuery(document).ready(function(){ jQuery("#profile_table").tablesorter(); }); </script><br />
<table id="profile_table" class="tablesorter">
<thead>
<tr>
<th scope=col>Time (seconds)</th>
<th scope=col>% of Total</th>
<th scope=col>Calls</th>
<th scope=col>Function</th>
<th scope=col>Actions / Filters</th>
</tr>
</thead>
<tbody>
<tr>
<td>0.042</td>
<td>12.3%</td>
<td>246</td>
<td>wptexturize</td>
<td>
<table class="profile-inner">
<tr>
<th scope=col>Time (seconds)</th>
<th scope=col>% of Total</th>
<th scope=col>Calls</th>
<th scope=col>Action / Filter</th>
</tr>
<tbody>
<tr>
<td>0.022</td>
<td>6.3%</td>
<td>1</td>
<td>the_content</td>
</tr>
<tr>
<td>0.008</td>
<td>2.2%</td>
<td>115</td>
<td>the_title</td>
</tr>
<tr>
<td>0.007</td>
<td>2.1%</td>
<td>37</td>
<td>comment_text</td>
</tr>
<tr>
<td>0.005</td>
<td>1.4%</td>
<td>79</td>
<td>list_cats</td>
</tr>
<tr>
<td><0.001</td>
<td>0.3%</td>
<td>14</td>
<td>bloginfo, link_name, link_description</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>0.023</td>
<td>6.5%</td>
<td>38</td>
<td>wpautop</td>
<td>
<table class="profile-inner">
<tr>
<th scope=col>Time (seconds)</th>
<th scope=col>% of Total</th>
<th scope=col>Calls</th>
<th scope=col>Action / Filter</th>
</tr>
<tbody>
<tr>
<td>0.013</td>
<td>3.7%</td>
<td>1</td>
<td>the_content</td>
</tr>
<tr>
<td>0.01</td>
<td>2.9%</td>
<td>37</td>
<td>comment_text</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>0.017</td>
<td>4.9%</td>
<td>38</td>
<td>convert_smilies</td>
<td>
<table class="profile-inner">
<tr>
<th scope=col>Time (seconds)</th>
<th scope=col>% of Total</th>
<th scope=col>Calls</th>
<th scope=col>Action / Filter</th>
</tr>
<tbody>
<tr>
<td>0.009</td>
<td>2.6%</td>
<td>1</td>
<td>the_content</td>
</tr>
<tr>
<td>0.008</td>
<td>2.3%</td>
<td>37</td>
<td>comment_text</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>0.01</td>
<td>3%</td>
<td>167</td>
<td>convert_chars</td>
<td>
<table class="profile-inner">
<tr>
<th scope=col>Time (seconds)</th>
<th scope=col>% of Total</th>
<th scope=col>Calls</th>
<th scope=col>Action / Filter</th>
</tr>
<tbody>
<tr>
<td>0.004</td>
<td>1.2%</td>
<td>115</td>
<td>the_title</td>
</tr>
<tr>
<td>0.003</td>
<td>0.8%</td>
<td>37</td>
<td>comment_text</td>
</tr>
<tr>
<td>0.003</td>
<td>0.8%</td>
<td>1</td>
<td>the_content</td>
</tr>
<tr>
<td><0.001</td>
<td>0.1%</td>
<td>14</td>
<td>link_name, link_description, bloginfo</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>0.007</td>
<td>2%</td>
<td>1</td>
<td>do_shortcode</td>
<td>the_content</td>
</tr>
<tr>
<td>0.007</td>
<td>2%</td>
<td>37</td>
<td>make_clickable</td>
<td>comment_text</td>
</tr>
<tr>
<td>0.006</td>
<td>1.8%</td>
<td>1</td>
<td>WP_Embed :: run_shortcode</td>
<td>the_content</td>
</tr>
<tr>
<td>0.004</td>
<td>1.2%</td>
<td>1</td>
<td>wp_cron</td>
<td>sanitize_comment_cookies</td>
</tr>
<tr>
<td>0.002</td>
<td>0.7%</td>
<td>1</td>
<td>wp_widgets_init</td>
<td>init</td>
</tr>
<tr>
<td>0.002</td>
<td>0.6%</td>
<td>1</td>
<td>profile_enqueue_requirements</td>
<td>init</td>
</tr>
<tr>
<td>0.002</td>
<td>0.5%</td>
<td>10</td>
<td>wp_filter_kses</td>
<td>
<table class="profile-inner">
<tr>
<th scope=col>Time (seconds)</th>
<th scope=col>% of Total</th>
<th scope=col>Calls</th>
<th scope=col>Action / Filter</th>
</tr>
<tbody>
<tr>
<td>0.001</td>
<td>0.3%</td>
<td>5</td>
<td>link_description</td>
</tr>
<tr>
<td>0.001</td>
<td>0.3%</td>
<td>5</td>
<td>link_name</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>0.002</td>
<td>0.5%</td>
<td>1</td>
<td>WP_Widget_Factory :: _register_widgets</td>
<td>widgets_init</td>
</tr>
<tr>
<td>0.001</td>
<td>0.4%</td>
<td>37</td>
<td>force_balance_tags</td>
<td>comment_text</td>
</tr>
<tr>
<td>0.001</td>
<td>0.4%</td>
<td>204</td>
<td>_config_wp_home</td>
<td>option_home</td>
</tr>
<tr>
<td>0.001</td>
<td>0.4%</td>
<td>1</td>
<td>wp_default_scripts</td>
<td>wp_default_scripts</td>
</tr>
<tr>
<td>0.001</td>
<td>0.2%</td>
<td>1</td>
<td>wp_print_head_scripts</td>
<td>wp_head</td>
</tr>
<tr>
<td>0.001</td>
<td>0.2%</td>
<td>1</td>
<td>feed_links_extra</td>
<td>wp_head</td>
</tr>
<tr>
<td>0.001</td>
<td>0.2%</td>
<td>37</td>
<td>kb_filter_avatar</td>
<td>get_avatar</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>0.135s</th>
<th>39.2%</th>
<th>1071</th>
</tr>
</tfoot>
</table>
<p><script type="text/javascript"> jQuery(document).ready(function(){ jQuery("#profile_db_table").tablesorter(); }); </script><br />
<table id="profile_db_table" class="tablesorter">
<thead>
<tr>
<th scope=col>Time (seconds)</th>
<th scope=col>% of Total</th>
<th scope=col>Function</th>
<th scope=col>Query</th>
</tr>
</thead>
<tbody>
<tr>
<td>0.002</td>
<td>0.6%</td>
<td>comments_template</td>
<td>SELECT * FROM wp_comments WHERE comment_post_ID = 144 AND (comment_approved = &#8216;1&#8242; OR ( user_id = 111 AND comment_approved = &#8216;0&#8242; ) )  ORDER BY comment_date_gmt</td>
</tr>
<tr>
<td>0.001</td>
<td>0.4%</td>
<td>get_pages</td>
<td>SELECT * FROM wp_posts  WHERE (post_type = &#8216;page&#8217; AND post_status = &#8216;publish&#8217;)     ORDER BY menu_order, post_title ASC</td>
</tr>
<tr>
<td>0.001</td>
<td>0.4%</td>
<td>update_meta_cache</td>
<td>SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (144)</td>
</tr>
<tr>
<td>0.001</td>
<td>0.2%</td>
<td>_fill_user</td>
<td>SELECT meta_key, meta_value FROM wp_usermeta WHERE user_id = 111</td>
</tr>
<tr>
<td>0.001</td>
<td>0.2%</td>
<td>get_bookmarks</td>
<td>SELECT *  , IF (DATE_ADD(link_updated, INTERVAL 120 MINUTE) >= NOW(), 1,0) as recently_updated   FROM wp_links  INNER JOIN wp_term_relationships AS tr ON (wp_links.link_id = tr.object_id) INNER JOIN wp_term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id WHERE 1=1 AND link_visible = &#8216;Y&#8217;  AND ( tt.term_id = 2 ) AND taxonomy = &#8216;link_category&#8217;    ORDER BY link_name ASC</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>0.01s</th>
<th>2.9%</th>
</tr>
</tfoot>
</table>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/wp-profile-plugin/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cache Translation Object v1.2</title>
		<link>http://devel.kostdoktorn.se/cache-translation-object-v1-2</link>
		<comments>http://devel.kostdoktorn.se/cache-translation-object-v1-2#comments</comments>
		<pubDate>Fri, 23 Oct 2009 11:07:17 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://devel.kostdoktorn.se/?p=43</guid>
		<description><![CDATA[Another new version of Cache Translation Object plugin released.
We need to whitelist which get_locale() calls we filter: load_plugin_textdomain() yes, get_bloginfo() no.
For the future I&#8217;m hoping to get a new filter to use.
]]></description>
			<content:encoded><![CDATA[<p>Another new version of <a href="http://devel.kostdoktorn.se/cache-translation-object">Cache Translation Object</a> plugin released.</p>
<p>We need to whitelist which <code>get_locale()</code> calls we filter: <code>load_plugin_textdomain()</code> yes, <code>get_bloginfo()</code> no.</p>
<p>For the future I&#8217;m hoping to get <a href="http://core.trac.wordpress.org/ticket/11012">a new filter</a> to use.</p>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/cache-translation-object-v1-2/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cache Translation Object v1.1</title>
		<link>http://devel.kostdoktorn.se/cache-translation-object-v1-1</link>
		<comments>http://devel.kostdoktorn.se/cache-translation-object-v1-1#comments</comments>
		<pubDate>Thu, 22 Oct 2009 23:38:45 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://devel.kostdoktorn.se/?p=42</guid>
		<description><![CDATA[New version of Cache Translation Object plugin released.
The major focus of this release is to handle multi-locale correctly &#8212; for example if you have one of the multi-language plugins, or if you use different languages on different installations on same host.
This was actually quite a bit of work to get working correctly for Shared Memory. [...]]]></description>
			<content:encoded><![CDATA[<p>New version of <a href="http://devel.kostdoktorn.se/cache-translation-object">Cache Translation Object</a> plugin released.</p>
<p>The major focus of this release is to handle multi-locale correctly &#8212; for example if you have one of the multi-language plugins, or if you use different languages on different installations on same host.</p>
<p>This was actually quite a bit of work to get working correctly for Shared Memory. Shared Memory objects doesn&#8217;t actually get deleted until every reference to the object is closed, from potentially multiple concurrent page load.<span id="more-42"></span></p>
<h3>Change Log</h3>
<p>Version 1.1</p>
<ul>
<li>Rewritten to cache multiple locales separately</li>
<li>Split out admin functions into separate file</li>
<li>Handle old SHM with questionable delete behaviour by relocating as necessary.</li>
<li>Add storage debug info link</li>
<li>Do not default to any specific storage type, make user choose</li>
<li>Tell admin when something is wrong (also better error handling).</li>
<li>Added plugin localization</li>
<li>Added Swedish translation</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/cache-translation-object-v1-1/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fix Performance Regression</title>
		<link>http://devel.kostdoktorn.se/fix-performance-regression</link>
		<comments>http://devel.kostdoktorn.se/fix-performance-regression#comments</comments>
		<pubDate>Tue, 20 Oct 2009 19:45:16 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://devel.kostdoktorn.se/?p=38</guid>
		<description><![CDATA[
A simple tool to benchmark web performance is Apachebench &#8212; which comes bundled with the Apache web server. To understand how a system as a whole performs you&#8217;ll need something more advanced but to just test how long it takes a page to load it works fine.
The graph above[1] expands on where I started profiling [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-40" title="Pageload regression fixes" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/pageload-fixes.gif" alt="Pageload regression fixes" width="529" height="465" /></p>
<p>A simple tool to benchmark web performance is <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">Apachebench</a> &#8212; which comes bundled with the Apache web server. To understand how a system as a whole performs you&#8217;ll need something more advanced but to just test how long it takes a page to load it works fine.</p>
<p>The graph above[<a href="http://devel.kostdoktorn.se/fix-performance-regression#note-1">1</a>] expands on where I started <a href="http://devel.kostdoktorn.se/profiling-wordpress-performance-regression">profiling the WordPress regression</a>. I&#8217;ve added the full 10 post frontpage and a single larger page &#8212; with rather lousy performance &#8212; and the work so far to remedy it which looks alot better.<span id="more-38"></span></p>
<p>Most of the performance back in just a handful of patches:</p>
<ul>
<li><a href="http://core.trac.wordpress.org/ticket/10972">#10972</a>: no need to sanitize a post more than once (merged in <a href="http://core.trac.wordpress.org/changeset/12062">12062</a>)</li>
<li><a href="http://core.trac.wordpress.org/ticket/10971">#10971</a>: translation performance when doing nothing (similar patch merged in <a href="http://core.trac.wordpress.org/changeset/12080">12080</a>)</li>
<li><a href="http://core.trac.wordpress.org/ticket/10987">#10987</a>: improve <code>wptexturize()</code> performance (merged in <a href="http://core.trac.wordpress.org/changeset/12084">12084</a>)</li>
</ul>
<p>Still on list of suspects: <code>wp_filter_kses()</code> (though <a href="http://core.trac.wordpress.org/ticket/10751">#10751</a>), <code>wp_widget_init()</code></p>
<p><strong>[<a name="note-1"></a>1]</strong> Numbers are total page load time average of 100 single threaded connections with a clean WordPress install, time is in milliseconds.</p>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/fix-performance-regression/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Profiling WordPress Performance Regression</title>
		<link>http://devel.kostdoktorn.se/profiling-wordpress-performance-regression</link>
		<comments>http://devel.kostdoktorn.se/profiling-wordpress-performance-regression#comments</comments>
		<pubDate>Sun, 18 Oct 2009 02:05:54 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://devel.kostdoktorn.se/?p=27</guid>
		<description><![CDATA[
I&#8217;ve been benchmarking stock WordPress today to get performance numbers for the Cache Translation Object plugin. As I had things set up for it I also tested  the latest major releases &#8211; unmodified, clean installations &#8211; and found a 40% regression when going from 2.7 to 2.8.
Update: what I measure here is basically the clean [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-28" title="Pageload regression" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/pageload-regression.gif" alt="Pageload regression" width="529" height="261" /></p>
<p>I&#8217;ve been benchmarking stock WordPress today to get performance numbers for the <a href="http://devel.kostdoktorn.se/cache-translation-object">Cache Translation Object</a> plugin. As I had things set up for it I also tested  the latest major releases &#8211; unmodified, clean installations &#8211; and found a <strong>40% regression</strong> when going from 2.7 to 2.8.</p>
<p><strong>Update:</strong> what I measure here is basically the clean startup time, which doesn&#8217;t say what the final effect will be on your site with a real theme, plugins and, you know, actual content.</p>
<p>There is often a battle between features, complexity and performance. This unfortunately natural tendency prevalent among programmers should however not result in such a drastic regression.</p>
<p><strong>Update 2:</strong> More on this <a href="http://devel.kostdoktorn.se/fix-performance-regression">here</a>.</p>
<p><span id="more-27"></span></p>
<h3>Profiling Performance Regressions</h3>
<p>There are <strong>a lot</strong> of changes in any major release of  a project the size of WordPress so finding the actual culprits in these cases are not always easy &#8212; though in this case some of it turned out to be surprisingly simple.</p>
<p>One way to find performance problems is to <a href="http://codex.wordpress.org/Testing_WordPress_Performance">profile</a> the two versions and compare. Here you can see lists of the cumulatively most expensive functions with 2.7 to the left and 2.8 to the right:</p>
<div id="attachment_34" class="wp-caption aligncenter" style="width: 561px"><img class="size-full wp-image-34" title="WordPress 2.7 vs 2.8 Profile" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/profile-27-vs-28.gif" alt="WordPress 2.7 vs 2.8 Profile" width="551" height="413" /><p class="wp-caption-text">WordPress 2.7 vs 2.8 Profile</p></div>
<p>I&#8217;ve marked some interesting parts in the 2.8 profile. What you want to look for are functions that takes proportionally longer to execute and figure out why. <a href="http://kcachegrind.sourceforge.net/html/Home.html">KCachegrind</a> (or WinCachegrind) gives many helpful views of call-chains and such things.</p>
<p>In this case the yellow-marked functions are calling the red-marked translation functions which suddenly consumes major resources. Doing nothing, it should be noted as the stock install doesn&#8217;t need anything translated.</p>
<h3>A victim of Abstraction</h3>
<p>So the first, and largest, culprit turns out to be this piece of code:</p>
<pre>function &amp;get_translations_for_domain( $domain ) {
	global $l10n;
	$empty = &amp;new Translations;
	if ( isset($l10n[$domain]) )
		return $l10n[$domain];
	else
		return $empty;
}</pre>
<p><img class="alignright size-full wp-image-36" title="Pageload regression fix1" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/pageload-regression-fix1.gif" alt="Pageload regression fix1" width="293" height="226" />Not setting up and calling an calling an empty Translations object <strong>increases performance again by 17%</strong>.</p>
<p>The rest of the regression seems to be mostly caused by changes in <code>sanitize_post()</code>, wp_widgets_init and <code>sanitize_bookmark_field(),</code> which I&#8217;ll look at next &#8212; tomorrow.</p>
<p>Anyone testing WordPress performance?</p>
<p><strong>Update:</strong> With two patches we get back half of the lost performance.</p>
<p><strong>Update 2:</strong> More on this <a href="../fix-performance-regression">here</a> as noted above.</p>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/profiling-wordpress-performance-regression/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The WordPress Localization Performance Battle</title>
		<link>http://devel.kostdoktorn.se/the-wordpress-localization-performance-battle</link>
		<comments>http://devel.kostdoktorn.se/the-wordpress-localization-performance-battle#comments</comments>
		<pubDate>Fri, 16 Oct 2009 11:22:27 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://devel.kostdoktorn.se/?p=19</guid>
		<description><![CDATA[
Using WordPress translated to your own language results in a surprisingly large performance cost. In my tests it took twice (or four times!) as long for an unmodified WordPress 2.8.4 start page to load when using a localized WordPress.
Translating a lot of text in an user friendly fashion is hard to do efficiently.
But there are [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-20" title="graph-1-284" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/graph-1-284.gif" alt="graph-1-284" width="528" height="274" /></p>
<p>Using WordPress translated to your own language results in a surprisingly large performance cost. In my tests it took twice (or four times!) as long for an unmodified WordPress 2.8.4 start page to load when using a localized WordPress.</p>
<p>Translating a lot of text in an user friendly fashion <strong>is</strong> hard to do efficiently.</p>
<p>But there are things we can do to make it a lot less painful.<span id="more-19"></span> Most of the time is actually spent when WordPress reads the MO files containing all text to translate and structures it into the l10n object to prepare for the translations to come. On each page load.</p>
<p>The obvious solution is to cache the resulting object. <a href="http://devel.kostdoktorn.se/cache-translation-object">So I did</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/the-wordpress-localization-performance-battle/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Limit Login Attempts 2.0beta3</title>
		<link>http://devel.kostdoktorn.se/limit-login-attempts-2-0beta3</link>
		<comments>http://devel.kostdoktorn.se/limit-login-attempts-2-0beta3#comments</comments>
		<pubDate>Sat, 10 Oct 2009 18:07:53 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://devel-test.kostdoktorn.se/?p=9</guid>
		<description><![CDATA[Consider trying this beta version of the Limit Login Attempts plugin&#8211; it should be more or less finished. Please post any problems (or successes).
The major focus of this new version is to protect the user login names of privileged users from discovery. Which, it turns out, is a lot of work to do correctly.
It includes [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-10" title="Registration Lockout" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/2-0beta3-2-8-4-reg-lockout-fullsize.gif" alt="Registration lockout" />Consider <a title="Limit Login Attempts download page" href="http://wordpress.org/extend/plugins/limit-login-attempts/download/">trying this beta version</a> of the <a href="http://devel.kostdoktorn.se/limit-login-attempts">Limit Login Attempts</a> plugin&#8211; it should be more or less finished. Please post any problems (or successes).</p>
<p>The major focus of this new version is to protect the user login names of privileged users from discovery. Which, it turns out, is a lot of work to do correctly.</p>
<p>It includes optional restrictions on password reset attempts and new user registrations. The plugin also helps you see and modify the various names Wordpress keep for each user. By default Wordpress uses the user login name to construct author archive URLs, nickname, displayname and so on.</p>
<p>It also allows you to change the URL name of users. I actually find it rather strange that there is no way to change it in stock WordPress.</p>
<p>Remaining on the todo list: Translations, the readme.txt, some documentation, and some further testing.</p>
<p>Screenshots of new settings: <a href="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/2-0beta3-2-8-4-settings-fullsize.gif">2.8.4</a>, <a href="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/2-0beta3-2-5-settings-fullsize.gif">2.5</a></p>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/limit-login-attempts-2-0beta3/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Faster Smilies</title>
		<link>http://devel.kostdoktorn.se/faster-smilies</link>
		<comments>http://devel.kostdoktorn.se/faster-smilies#comments</comments>
		<pubDate>Sat, 10 Oct 2009 17:52:58 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[deprecated]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://devel-test.kostdoktorn.se/?p=7</guid>
		<description><![CDATA[A Deprecated Wordpress Plugin.
When working on profiling a Wordpress install I found, to my surprice that for a 400 comment post the single most expensive thing was translating smilies to pictures &#8212; 55% of time to create the page!
Apart from sending a patch fixing this (which went into Wordpress 2.8) I also made a small [...]]]></description>
			<content:encoded><![CDATA[<p>A Deprecated Wordpress Plugin.<img class="size-full wp-image-8 alignleft" title="smilies-cost" src="http://devel.kostdoktorn.se/wp-content/uploads/2009/10/smilies-cost.gif" alt="smilies-cost" width="150" height="147" /></p>
<p>When working on profiling a Wordpress install I found, to my surprice that for a 400 comment post the single most expensive thing was translating smilies to pictures &#8212; 55% of time to create the page!</p>
<p>Apart from sending a patch fixing this (which went into Wordpress 2.8) I also made a small plugin to use before the new version was available.</p>
<p>It is no longer useful as everyone should be using a modern Wordpress version.</p>
<p>It can be found <a href="http://wordpress.org/extend/plugins/faster-smilies/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/faster-smilies/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Limit Login Attempts 2.0beta2</title>
		<link>http://devel.kostdoktorn.se/limit-login-attempts-2-0beta2</link>
		<comments>http://devel.kostdoktorn.se/limit-login-attempts-2-0beta2#comments</comments>
		<pubDate>Sat, 03 Oct 2009 23:02:21 +0000</pubDate>
		<dc:creator>Johan Eenfeldt</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://devel-test.kostdoktorn.se/?p=6</guid>
		<description><![CDATA[Consider trying this beta version. Please post any problems (or successes).
The major focus of this new version is to hide the username of privileged users. Which, it turns out, is a lot of work to do correctly.
It includes optional restrictions on password reset attempts and new user registrations. It also lists any privileged users whose [...]]]></description>
			<content:encoded><![CDATA[<p>Consider <a title="Limit Login Attempts download page" href="http://wordpress.org/extend/plugins/limit-login-attempts/download/">trying this beta version</a>. Please post any problems (or successes).</p>
<p>The major focus of this new version is to hide the username of privileged users. Which, it turns out, is a lot of work to do correctly.</p>
<p>It includes optional restrictions on password reset attempts and new user registrations. It also lists any privileged users whose username as the various names displayed on the blog. Which by default is all of them as Wordpress default uses the username to construct author archive URLs, among other things.</p>
<p>Largest missing piece is functionality to modify username (which might possibly be dangerous to do) and &#8220;nicename&#8221; (which might invalidate previous author archive URLs).</p>
]]></content:encoded>
			<wfw:commentRss>http://devel.kostdoktorn.se/limit-login-attempts-2-0beta2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
