<?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"
	>

<channel>
	<title>neodude.net</title>
	<atom:link href="http://neodude.net/feed" rel="self" type="application/rss+xml" />
	<link>http://neodude.net</link>
	<description>Sorta has that smell of wood sawed by a machine, one that makes them all identical</description>
	<pubDate>Thu, 29 May 2008 06:08:32 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>WordPress Caching: Day&#160;1</title>
		<link>http://neodude.net/archives/2008/05/wordpress-caching-day-1</link>
		<comments>http://neodude.net/archives/2008/05/wordpress-caching-day-1#comments</comments>
		<pubDate>Thu, 29 May 2008 00:50:47 +0000</pubDate>
		<dc:creator>neodude</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[gsoc2008]]></category>

		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://neodude.net/?p=16</guid>
		<description><![CDATA[A little late to the game (gsoc officially started on Monday), but I&#8217;m up and running now. The guiding aim of this project is to &#8220;raise the amount of traffic a vanilla WP install can take&#8221;, by improving the built-in cache support of WP. That&#8217;s the idea anyway; who knows where it&#8217;ll take me. Andy&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>A little late to the game (<a href="http://code.google.com/soc">gsoc</a> officially started on Monday), but I&#8217;m up and running now. The guiding aim of <a href="http://code.google.com/soc/2008/wordpress/appinfo.html?csaid=7E1A38664ABC103C">this project</a> is to &#8220;raise the amount of traffic a vanilla WP install can take&#8221;, by improving the built-in cache support of WP. That&#8217;s the idea anyway; who knows where it&#8217;ll take me. <a href="http://andy.wordpress.com/">Andy</a>&#8217;s mentoring the&nbsp;project.</p>
<p>Spent most of today fiddling around the idea, and Andy and I decided to set up a benchmarking environment; a systematic, easily-repeatable way to stress a WP install. After crashing the neodude.net server a couple of times (at one point, linux was allocating ~6MB of swap space <em>per second</em>), I found and resurrected my old laptop. Installing ubuntu on a computer without USB nor CD booting turned out to be remarkably easy: with Windows on the computer, installing took 5 minutes of clicking with <a href="http://unetbootin.sourceforge.net/">unetbootin</a>, and an hour of waiting. Scuffles with the Dartmouth network made things take longer than it&nbsp;should.</p>
<p>As for load-testing: spent a lot of time messing around with <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">ab</a>, the benchmark program that comes with Apache httpd. ab isn&#8217;t very full-featured though; we want to simulate the internet&#8217;s load on the testing server (both normal and digg loads), and you can&#8217;t even have ab hit more than one URL at a&nbsp;time.</p>
<p>Then found <a href="http://www.joedog.org/JoeDog/Siege">Siege</a>, which looks to be the perfect tool. It&#8217;s literally designed exactly for the stress benchmarking we&#8217;re trying to do here. Planning to set up some php scripts to easily invoke Siege in different scenarios, will see how things go. Maybe suck data into mysql tables for optimal fun-to-data ratio. Here&#8217;s some fun siege stats that gave a load average of 22.69 in the last minute:<br />
<code><br />
$ siege --file=urls.txt -i -c40 -t 1M<br />
...<br />
Transactions:		         314 hits<br />
Availability:		      100.00 %<br />
Elapsed time:		       59.46 secs<br />
Data transferred:	        2.13 MB<br />
Response time:		        6.59 secs<br />
Transaction rate:	        5.28 trans/sec<br />
Throughput:		        0.04 MB/sec<br />
Concurrency:		       34.81<br />
Successful transactions:         314<br />
Failed transactions:	           0<br />
Longest transaction:	       13.17<br />
Shortest transaction:	        1.79<br />
</code></p>
<p>Also found <a href="http://www.linklint.org/">linklint</a> after hours of searching for a way to extract out a comprehensive list of links from a site. My unix kung-fu is&nbsp;lacking.</p>
]]></content:encoded>
			<wfw:commentRss>http://neodude.net/archives/2008/05/wordpress-caching-day-1/feed</wfw:commentRss>
		</item>
		<item>
		<title>&#8220;That told me a&#160;lot.&#8221;</title>
		<link>http://neodude.net/archives/2008/04/that-told-me-a-lot</link>
		<comments>http://neodude.net/archives/2008/04/that-told-me-a-lot#comments</comments>
		<pubDate>Wed, 02 Apr 2008 22:34:34 +0000</pubDate>
		<dc:creator>neodude</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[comments]]></category>

		<category><![CDATA[funny]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://neodude.net/?p=12</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="http://neodude.net/wp-content/uploads/2008/04/picture-1.png"><img class="aligncenter size-full wp-image-13" title="useless-comment" src="http://neodude.net/wp-content/uploads/2008/04/picture-1.png" alt="Image showing a comment explaining the variable $ids.. with \" width="375" height="87"&nbsp;/></a></p>
<p>This may be perhaps the most useless comment I&#8217;ve ever written. The bummer is, it&#8217;s not immediately obvious what the containing function does. Hence, this artifact was too ironic to not&nbsp;document.</p>
]]></content:encoded>
			<wfw:commentRss>http://neodude.net/archives/2008/04/that-told-me-a-lot/feed</wfw:commentRss>
		</item>
		<item>
		<title>Caching in&#160;WordPress</title>
		<link>http://neodude.net/archives/2008/03/caching-in-wordpress</link>
		<comments>http://neodude.net/archives/2008/03/caching-in-wordpress#comments</comments>
		<pubDate>Mon, 31 Mar 2008 07:42:56 +0000</pubDate>
		<dc:creator>neodude</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[gsoc2008]]></category>

		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://neodude.net/?p=11</guid>
		<description><![CDATA[(This introduction got a little longer than I thought it would be, so please bear with me in the next three&#160;paragraphs!)
I&#8217;m often surprised to find WordPress deployed in very large-scale sites; a good example would be, &#8220;Did you know that the New York Times runs their blogs on WordPress?!&#8221; I&#8217;m sure this is of no [...]]]></description>
			<content:encoded><![CDATA[<p>(This introduction got a little longer than I thought it would be, so please bear with me in the next three&nbsp;paragraphs!)</p>
<p>I&#8217;m often surprised to find WordPress deployed in very large-scale sites; a good example would be, &#8220;Did you know that the New York Times runs <a title="Link to the WordPress login for NYT's The Caucus" href="http://thecaucus.dblogs.nytimes.com/wp-admin/">their blogs</a> on WordPress?!&#8221; I&#8217;m sure this is of no surprise to the fellows at&nbsp;Automattic.</p>
<p>The New York Times, I&#8217;m sure, needs caching. Or if your blog is overrun by <a href="http://www.digg.com/">Digg</a>, <a href="http://slashdot.org/">Slashdot</a>, or the next click conduit of the interwebs, then you&#8217;ll definitely need caching. The solutions are there; the most critically acclaimed (currently) is <a href="http://ocaoimh.ie/wp-super-cache/">WP Super Cache</a>, by Donncha O Caoimh. It works by saving off your pages as static HTML files and mod_rewriting requests to the cached version. Fairly simple concept, and spectacularly well&nbsp;implemented.</p>
<p>WP Super Cache has a deceptively short list of requirements: Apache, mod_rewrite, and write access to the wp-content folder. If you&#8217;re running a large blog, you&#8217;ll most likely have the resources to control the environment it runs&nbsp;in.</p>
<p>But if you&#8217;re running your blog on some shared hosting service for two dollars a month, it might not be on an Apache server. There may be no mod_rewrite, or .htaccess access. There might not even be write access available, especially if you installed WordPress by clicking a button. Having never been subjected to PHP&#8217;s safe mode, I don&#8217;t know the particulars of its restrictions, but that&#8217;s a fairly large segment of the web population as&nbsp;well.</p>
<p>As I was contemplating what I&#8217;d like to apply for in Google&#8217;s Summer of Code, I tripped over one of WordPress&#8217; proposal ideas, namely, &#8220;<a href="http://codex.wordpress.org/GSoC2008#Integrated_Caching_Solutions">Integrated Caching Solutions</a>&#8220;. Having worked a bunch on <a href="http://thedartmouth.com/">TheDartmouth.com</a>&#8217;s caching system, I thought that I could bring something to the table&nbsp;there.</p>
<p>The basic idea, as I see it, is to raise the amount of traffic a vanilla WordPress install can take. Thus, by definition, I&#8217;d be looking to write a core patch to the WordPress codebase, because, honestly, the caching plugin market is very well catered to already (see above). The core infrastructure could, however, definitely use some&nbsp;love.</p>
<p>Consider the most restrictive hosting scenario possible – no write access, no .htaccess, no nothing. But you have a database to run WordPress with. For caching to work for everyone, it will need to cache into the&nbsp;database.</p>
<p>Luckily, the most difficult work has been done with the brand-new 2.5 release – WP_Object_Cache exists and caches data within each request. Previous to 2.5, there was a file-based caching solution that took serialized objects and cached them on disk; this was ripped out of the core because, <a href="http://comox.textdrive.com/pipermail/wp-hackers/2008-February/018134.html">according to DD32</a>, the code was not well-maintained, and hence there were more problems than&nbsp;benefits.</p>
<p>I think more performance can be squeezed out of a WordPress with database-backed, object-based caching verses without. It may not be a massive speedup – after all, you&#8217;ll still be spending a ton of time connecting to the database – but it would be faster than it is now. There must be the option of turning it off and falling back to the current per-request object caching, since it would be redundant to run a full-page caching solution (i.e. WP Super Cache) and a persistent, database-backed object cache as&nbsp;well.</p>
<p>I <a href="http://comox.textdrive.com/pipermail/wp-hackers/2008-March/018842.html">pitched this idea</a> to the <a href="http://comox.textdrive.com/pipermail/wp-hackers/">wp-hackers mailing list</a>, and Mahmoud Al-Qudsi was kind enough to do a <a href="http://comox.textdrive.com/pipermail/wp-hackers/2008-March/018860.html">quick proof-of-concept</a> for this idea. It didn&#8217;t work – taking the current memory-backed object cache as-is and moving it far, far away into the database makes page load time 4-5 times longer. However, I think implementing some more optimization would make this idea feasible – for example, pre-fetching a default set of objects from the cache at initialization, and saving all modified data to cache in one go, at the end of the request. Perhaps pages can have some hinting information built in about which objects to pre-fetch. Another idea is to have the caching engine automatically collect hinting data for each type of page. The first time each type of page is accessed it would be a little slow, but pretty fast from then on. The hints could then be stored in the cache itself (or somewhere else more permanent), and this solution would adapt to plugins&#8217; data access&nbsp;automatically.</p>
<p>The first thing to do, in implementing core caching, is to figure out if this is feasible. It&#8217;s the only solution that will work on all installations of WordPress out-of-the-box. Mahmoud sent me his code (so nice of him to, thank you thank you), so that&#8217;s something to work on the&nbsp;off-start.</p>
<p>Now that we have persistent object caching, the next logical step would be caching at higher levels – namely, full-page caching. If shipped with the core, it should definitely be a plugin, and probably disabled by default; there are definitive drawbacks to caching whole pages, namely that dynamic content (e.x., random ordering of links) isn&#8217;t anymore. Of course, WordPress could not cache pages with dynamic content, but some users will have dynamic content on every page – say, an advertising system that displays a random ad per request. In this case, object-based caching will have to do, or perhaps, through the widget system, there could be a way of marking sections of pages as dynamic, and cache the page with sections to be replaced. This might not be worth it for the overhead,&nbsp;though.</p>
<p>Back to vanilla full-page caching: the obvious thing to do here is to integrate WP Super Cache into the WordPress core, if Donncha O Caoimh is OK with that, since there is no point in reinventing an already spectacularly done wheel. The big task will be to expand it to be able to cache to database with our fancy new framework from above. A simple check – whether we have .htaccess write access – will tell us whether to cache to database or file. It&#8217;ll also be worth investigating which pages can be full-page cached, and which can&#8217;t. WP Super Cache can tell us that, to some extent – but that might be able to be better&nbsp;defined.</p>
<p>A persistent caching system, regardless of being stored in database or as files, needs to be quite a bit more sophisticated. Someone famous once said that (paraphrasing) the most difficult problem in computer science is cache invalidation. The cache will need to kept both <strong>current</strong>, with the freshest content, and <strong>relevant</strong>, with the most-hit content, as the classic Digg/Slashdot effect often just hits one page over and over again. We&#8217;re also possibly working with a very restricted cache size (i.e. typical shared hosting database limits), so we&#8217;ll need to remove cache entries that may be current, but fairly&nbsp;old.</p>
<p>To accomplish a current and relevant cache, we&#8217;ll need to keep track of when a cache entry was last hit. In a database, that&#8217;s a fairly cheap INT field, and on a file it would obviously be the last accessed date. We should also keep statistics on how much a cache entry has been hit, just for statistical purposes (everyone loves big numbers attached to vaguely meaningful&nbsp;things).</p>
<p>The caching API will therefore need some equivalence to a &#8216;get_most_state_entry&#8217; method, which will get the cache entry that was last accessed the longest time ago. When the cache is full, a request to cache a new object will remove this oldest cache entry. This will keep the cache relevant; if a slashdot effect yesterday caused one cache entry to be hit 10,000 times, today&#8217;s digg effect on a different page will quickly knock the old cache entry off – since the torrent of new cache entries created by the dugg page will give the slashdotted page&#8217;s caches the oldest last accessed&nbsp;date.</p>
<p>For keeping the cache current&#8230; it would seem that we wouldn&#8217;t need to do this at all, assuming that every possible way to modify the database first goes through the caching system. That is, assuming that the caching API has 100% coverage of data access&nbsp;&#8216;paths&#8217;.</p>
<p>If we didn&#8217;t have 100% coverage – which, even if we did, is perhaps not a good thing to assume – then we have a cache invalidation problem. Luckily, Andy Skelton has a novel idea of using <a href="http://andy.wordpress.com/2008/03/01/cache-with-versioned-tags/">versioned tags on cache entries</a>. If I understood him correctly, the idea is to have an array, possibly stored in the cache itself, that is loaded on every request. This array would maintain the version status of, say, every WordPress table. Every time a table is changed, the version changes as well. Each cache entry would be hashed with the versions of the tables it uses, so when the version changes on a particular table, there is no cache invalidation needed – all the old entries with data from that table will automatically become impossible to access. Another way to implement this would be through the group mechanism already in&nbsp;WP_Object_Cache.</p>
<p>The above-described last-accessed-date flushing will eventually flush these dead entries out of the cache. We could maintain compatibility with pre-fetching common data objects, at the expense of having two queries at a request&#8217;s start instead of one: the first to get the version array, and the second to query for the common objects (since we need the version info to generate the correct&nbsp;hash).</p>
<p>This versioning information will go very well with full-page caching, and full-page caching will look a lot more like caching any serialized&nbsp;object. </p>
<p>All this implementation of cache techniques can go into the core, and can be selectively enabled, as needed. This way, any caching plugin built on top of this new API can take advantaged of versioned tags, last-accessed-date flushing,&nbsp;etc.</p>
<p>Here are some more implementation details that I&#8217;ve pondered&nbsp;on.</p>
<ul>
<li><strong>Modularity</strong>: This would essentially form the Caching API that additional caching plugins should use, most probably by forking the current WP_Object_Cache class and wp_cache_* functions, with additions for full HTML page caching, last-accessed-date flushing, versioned tags and so forth. Sketching out a good structure would take up a significant amount of time before implementation, because planning is good. It should also get some &#8217;stamp of approval&#8217; on wp-hackers. </li>
<li><strong>Administration Interface</strong>: It would be nice if there was some way of switching between caching plugins without having to edit files. Making a way for plugins to self-identify as a caching plugin so they will show up in the selection page would be good. I don&#8217;t want to duplicate too much of the available plugin functionality; just one new page to select the caching method, and let each plugin add their own pages for further configuration – just like WP Super Cache now.</li>
<li><strong>Storage/Table Type</strong>: There&#8217;ll need to be support for MyISAM, InnoDB, and MEMORY caching tables, unless there isn&#8217;t a way for shared hosting providers to disable MEMORY tables in MySQL. MEMORY tables will require some splitting mechanism to fit into its rigid row length requirement. The old, file-based caching code could also be reintegrated, if only as a caching plugin.</li>
<li><strong>Limited Database Size</strong>: The database cache will need to keep itself within a certain size, as a lot of shared hosting have database size limits. Unless there&#8217;s a MySQL configuration parameter to check, I think the user will need to enter this. At any rate, the database cache shouldn&#8217;t be allowed to rampantly eat all the disk space (because it will). Maybe a default size of.. 50 MB?</li>
<li><strong>Hashing</strong>: There will need to be a way to differentiate, by hash, a &#8216;global&#8217; object&#8217;s cache entry – e.x., alloptions – from a specific post&#8217;s cache entry. I suppose hashing the ID with the cache entry name will suffice. This may already be implemented into WP_Object_Cache with the $global_groups variable – I wasn&#8217;t particularly sure what that does right now.</li>
</ul>
<p>The best thing about all that&#8217;s been described so far is that it is compatible with any environment that will currently run a vanilla WordPress blog. Existing plugins - WP Super Cache, the old file-based caching code, memcached clusters – can all run on top of this API. The idea is that they&#8217;ll get more performance from this infrastructure as well, especially from the full-page&nbsp;caching.</p>
<p>Wow. What a lot of text. If you&#8217;ve gotten this far, I congratulate and sincerely thank you. Do leave a comment with your&nbsp;thoughts.</p>
]]></content:encoded>
			<wfw:commentRss>http://neodude.net/archives/2008/03/caching-in-wordpress/feed</wfw:commentRss>
		</item>
		<item>
		<title>Hello, unadorned&#160;World</title>
		<link>http://neodude.net/archives/2008/03/hello-unadorned-world</link>
		<comments>http://neodude.net/archives/2008/03/hello-unadorned-world#comments</comments>
		<pubDate>Fri, 28 Mar 2008 19:43:22 +0000</pubDate>
		<dc:creator>neodude</dc:creator>
		
		<category><![CDATA[Meta]]></category>

		<category><![CDATA[introduction]]></category>

		<category><![CDATA[neodudedotnet]]></category>

		<guid isPermaLink="false">http://telperion.local/nd8/?p=10</guid>
		<description><![CDATA[Now, originally, I had wanted to release a brand-new version of the site, all adored with design and attention. It would have been great - I would finally restart a too-long deserted effort, and have an actual website! Write a blog again! Post photos! Maybe even twitter&#160;(shock!).
Unfortunately, not only does design and attention take much [...]]]></description>
			<content:encoded><![CDATA[<p>Now, originally, I had wanted to release a brand-new version of the site, all adored with design and attention. It would have been great - I would finally restart a too-long deserted effort, and have an actual website! Write a blog again! Post photos! Maybe even twitter&nbsp;(shock!).</p>
<p>Unfortunately, not only does design and attention take much longer time than I think, my grasp of what I want for neodude.net is not nearly firm enough for me to work&nbsp;efficiently.</p>
<p>Instead, this time around, I&#8217;m just going to put the conduit up without the flair. Instead, I&#8217;ll have all the time in the world to make something wonderful. If I have it in me to be my own&nbsp;client.</p>
<p>Hello, naked&nbsp;world.</p>
]]></content:encoded>
			<wfw:commentRss>http://neodude.net/archives/2008/03/hello-unadorned-world/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
