<?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>Garrett Bluma</title>
	<atom:link href="http://garrettbluma.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://garrettbluma.com</link>
	<description>Web Developer</description>
	<lastBuildDate>Tue, 17 Aug 2010 05:20:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Nginx / Memcached Direct Page Caching</title>
		<link>http://garrettbluma.com/2010/08/16/nginx-memcached-direct-page-caching/</link>
		<comments>http://garrettbluma.com/2010/08/16/nginx-memcached-direct-page-caching/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 04:57:55 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[Joomla]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://garrettbluma.com/?p=313</guid>
		<description><![CDATA[There are a few different approaches to caching; data caching, fragment caching, and full-page caching. But first, here&#8217;s the typical model of a web application. User requests a page, and it works through the web server, through several layers, and finally to the database. Data caching takes the place of a database call and can [...]]]></description>
			<content:encoded><![CDATA[<p>There are a few different approaches to caching; data caching, fragment caching, and full-page caching. But first, here&#8217;s the typical model of a web application. User requests a page, and it works through the web server, through several layers, and finally to the database.</p>
<p><img class="aligncenter size-full wp-image-331" title="Typical webapp flow chart" src="http://garrettbluma.com/wp-content/uploads/2010/08/server-caching1.png" alt="" width="602" height="101" /></p>
<p><strong>Data caching </strong>takes the place of a database call and can be effective if there are a lot of database requests.  You would typically want to do this if you know that a piece of data is very common and unlikely to change. This saves time on one step of the process.</p>
<p><img class="aligncenter size-full wp-image-332" title="Web app flowchart 2" src="http://garrettbluma.com/wp-content/uploads/2010/08/server-caching2.png" alt="" width="602" height="102" /></p>
<p><strong>Fragment caching</strong> is a little more complicated.  Instead of caching the data that you would input into another process to build a layout (for example), you just cache that layout directly.  This is great for a &#8220;featured news&#8221; section that changes only once a day and is viewed often.  It would be silly to cache that data and calculate the layout for every view, so instead we would just cache the layout itself. Saves a bunch of work.</p>
<p>Moving on, we have <strong>page caching</strong>.  Which is the topic which I really want to go over. I have a warning though, page caching is dumb. REAL dumb. But, in that magnificent dumness is speed. Page caching is the most efficient of the three. It takes the gains we get from fragment caching and goes even further. Think about it, we hardly need to do anything—and therein lies the problem, we lose ALL dynamic ability of the page. This is not an issue for a lot of sites; news pages, catalogs, and blogs can all benefit from this method of caching.</p>
<p style="text-align: center;"><img class="size-full wp-image-333  aligncenter" title="Memcache flowchart" src="http://garrettbluma.com/wp-content/uploads/2010/08/server-caching3.png" alt="" width="449" height="102" /></p>
<p style="text-align: center;">. . .</p>
<p>The method I describe here I used allowed a <em>real</em> site to receive 250,000 <em>real</em> page-views in 40 min (~104 requests/sec). I expect you can do much more. (More number towards the end.)</p>
<p>What I haven&#8217;t mentioned yet is that I&#8217;m using PHP (specifically Joomla). PHP is certainly not the fastest language around, but considering the whole spectrum of issues facing a web developer, script performance is minimal. And since I&#8217;m on this rabbit trail, I&#8217;ll mention that <a href="http://developer.yahoo.com/performance/rules.html">Javascript/CSS is the first thing to fix</a>, then caching. I don&#8217;t need to explain more about this, there are volumes about it already.</p>
<p style="text-align: center;">. . .</p>
<p>Moving on, the method described for page caching is based on a simple fallback plan. Here is the psudo-code.</p>
<pre>If the page requested is in cache
    serve cached version
otherwise
    serve it dynamically
    add result to memcached</pre>
<p style="text-align: center;">. . .</p>
<p><strong>Joomla Plugin</strong></p>
<p>With Joomla we can actually do this very easily. We just need to hook into the <em>onAfterRender</em> event and grab the page data.  You might notice we&#8217;re using the database name as the prefix to the URL in the key name. This is just to be friendly to any other sites hosted on the same server (or copies of the same site using a different database).</p>
<p>You also might notice that we&#8217;re grabbing the gzipped version of the page. This is just to trim a little off what the user needs to download.</p>
<pre>// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.plugin.plugin' );

class  plgSystemFullPageMemcache extends JPlugin
{
    function plgSystemFullPageMemcache(&amp; $subject, $config) {
        parent::__construct($subject, $config);
    }

    function onAfterRender() {
        global $mainframe;
        $config = new JConfig();
        $cache_id= $config-&gt;db . ":" . $_SERVER['REQUEST_URI'];

        $data = JResponse::toString($mainframe-&gt;getCfg('gzip'));

        $db = new Memcache;
        $db-&gt;addServer('127.0.0.1', '11211', true);
        $db-&gt;set($cache_id, $data, 1, 3600);
    }
}</pre>
<p><strong>Nginx configuration</strong></p>
<pre>server {

  listen 80;
  server_name  yourdomain.com www.yourdomain.com;

  # ...

  location ~ \.php$ {
    set $memcached_key "yourdomain:$request_uri";
    memcached_pass 127.0.0.1:11211;

    default_type       text/html;
    error_page 404 405 502 = @cache_miss;
  }

  location @cache_miss {
    fastcgi_pass 127.0.0.1:9002;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/yoursite/htdocs$fastcgi_script_name;
    include /etc/nginx/fastcgi_params;
  }

  # ...
}</pre>
<p style="text-align: center;">. . .</p>
<p>Here you can see <em>@cache_miss</em> will get called when nginx can&#8217;t find anything in the memcache for the given key (the url). This triggers our fallback plan where the cache will fill itself with any missing data. When we do hit the cache, we actually bypass PHP altogether. No initialization wait, no slowness, and no database calls. By educated guess, nginx and memcached in this setup can start serving content in under 15 milliseconds. Compare this with the 50-100 milliseconds we commonly see.</p>
<p>Theoretically you could serve content faster using this system than just using files due to time spent waiting on disk access. In my proof of concept, I was able to serve about 2500 requests/second but I have reason to believe that limit was imposed by the network card. The CPU was at 10% the whole time and I&#8217;m sure it could handle more.</p>
<p>Happy caching!</p>
<p>(Downloadable Plugin Coming Soon)</p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2010/08/16/nginx-memcached-direct-page-caching/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Communicating Honestly</title>
		<link>http://garrettbluma.com/2010/07/27/communicating-honestly/</link>
		<comments>http://garrettbluma.com/2010/07/27/communicating-honestly/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 03:42:24 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://garrettbluma.com/?p=302</guid>
		<description><![CDATA[Most people suck at communicating—and I&#8217;m one of them. I get passionate about this issue because, really, it&#8217;s such an simple thing to change. Reordering a few words, pulling a few out, and generally saying less can have a profound impact—but then, why is it so hard? Because it&#8217;s hard to be honest, and it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Most people suck at communicating—and I&#8217;m one of them.</p>
<p>I get passionate about this issue because, really, it&#8217;s such an simple thing to change. Reordering a few words, pulling a few out, and generally saying less can have a profound impact—but then, why is it so hard?</p>
<p>Because it&#8217;s hard to be honest, and it&#8217;s hard to hear honesty.</p>
<p>I&#8217;m a perfect example of this.</p>
<p><strong>I make elaborate fabrications</strong> to sound well-informed when, really, I don&#8217;t have a clue what&#8217;s going on. It would be better to admit I&#8217;m clueless and move on. But, I could lose my contract, or my credibility! Who would want to work with me!? Well, personally, I would rather work with someone like that . And I can&#8217;t be the only one.</p>
<p><strong>I get defensive.</strong> I don&#8217;t like being put on the spot, I&#8217;m sure you can relate. And I&#8217;ll come up with some fancy excuse for why I &#8220;can&#8217;t hang out&#8221;, &#8220;can&#8217;t meet my deadline&#8221;, or &#8220;won&#8217;t share my source code.&#8221; This might work for a short while, but I always have the sneaking suspicion that it will catch up to me.</p>
<p><strong>I water down.</strong> Do you ever say something and then instantly regret it? I do this all the time. And then in order to cover it up you say all kinds of clever stuff to try and paint it in nicer light. Not cool. Stop it.</p>
<p>Yes, it&#8217;s hard to say what you actually mean. But it&#8217;s really the only option. The time lost while confusing people is expensive. During a booming economy, that might be overlooked. During an recession, watch out.</p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2010/07/27/communicating-honestly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programming and Practice</title>
		<link>http://garrettbluma.com/2010/07/13/programming-and-practice/</link>
		<comments>http://garrettbluma.com/2010/07/13/programming-and-practice/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 05:00:03 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Web Programming]]></category>

		<guid isPermaLink="false">http://garrettbluma.com/?p=290</guid>
		<description><![CDATA[I’ve been thinking about practice lately—and about growth. Here are some thoughts: Programming is a complicated job. Many people see it as a craft, and as craftsmen, programmers must spend countless hours honing their skills and improving their expertise to reach a level to compete at the level they desire to be at. For example: [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been thinking about practice lately—and about growth. Here are some thoughts:</p>
<p>Programming is a complicated job. Many people see it as a craft, and  as craftsmen, programmers must spend countless hours honing their skills  and improving their expertise to reach a level to compete at the level  they desire to be at. For example:</p>
<ul>
<li>If I want to build web pages at an <strong>amateur</strong> level, I  simply need to know HTML, some CSS, and maybe some jQuery. For every  question that might come up, there is usually a hundred answers on  Google.</li>
<li>If I want to do the same thing at an <strong>expert</strong> level, I  must know about usability, cross-browser compatibility, form  validation, race-condition debugging, and a host of other things—most  importantly, however, I should be able to find answers to problems that  are not Google-able.</li>
</ul>
<p>So if you’re shooting for your “A” game, you need to practice, right?.</p>
<p>But there’s a problem too. If <strong>anyone</strong> has an issue  with repetitiveness, it must be programmers. We have actually been  taught that the sole purpose for our job is to <em>reduce</em> repetitiveness. So where does that leave practice and doing things multiple times?</p>
<p>A lot of the programmers I know, who are really good, attribute their  success to the fact that they spend hours at home every night building  cool stuff or researching—I think the same could be said of artists and writers as well.</p>
<p>This is great, but let’s consider the following quote by Geoffrey Colvin (emphasis added).</p>
<blockquote><p>For example: <strong>Simply hitting a bucket of balls is not deliberate practice</strong>, which is why most golfers don’t get better. Hitting an eight-iron 300 times <strong>with a goal</strong> of leaving the ball within 20 feet of the pin 80 percent of the time, <strong>continually observing results</strong> and <strong>making appropriate adjustments</strong>, and doing that <strong>for hours every day</strong> &#8211; that’s deliberate practice.</p></blockquote>
<p>So let’s make an assumption—perhaps an incorrect one, but bear with me.</p>
<blockquote><p>Most programmers are not <em>deliberate</em> about <strong>what</strong> they practice or how they grow. They <strong>do not</strong> set clear goals, they <strong>do not</strong> continually measure results, however they <strong>are</strong> spending the necessary time.</p></blockquote>
<p>Why are we just like the golfers?—”simply hitting a bucket of balls.”</p>
<ul>
<li> <strong>Programmers don&#8217;t get out enough. <span style="font-weight: normal;">In particular with other that practice the same craft.</span></strong><strong> </strong></li>
<li> <strong>It’s still a fairly new craft. </strong>Many <em>outsiders </em>(your family, bosses, etc.) still think  that we just “know computers” and they come to us for everything  relating to computers. To them cleaning viruses and building web-pages  are the same thing. So, to cater to their needs, we are often forced to  become jacks-of-all-trades.</li>
<li> <strong>The web it too noisy</strong>. How do we judge what is important  given the thousands of new articles written every day? The best thing we  can do is probably unplug from the web and go for a walk.</li>
</ul>
<p>Here are some possible solutions. Certainly not an exhaustive list, but something to get started with.</p>
<ul>
<li> <strong>Local user groups.</strong> These allow for interaction, they expose people to higher-level talks and foster an environment for learning beyond amateur.</li>
<li> <strong>Set clear learning goals </strong>like “I want to understand exactly how Object Oriented CSS works” or “Find out mathematically if database XYZ can scale for a certain use-case”.</li>
<li> <strong>Continually measure results</strong>. Progress is important and  it might seem daunting that understanding CSS in 13 browsers is a  huge task, but every time you check one off, you’ll feel good about it.</li>
</ul>
<p>And although I don’t follow my own advice fully yet, I’ve determined to move forward with some of my own goals:</p>
<ul>
<li>Develop a system for building web UI applications that actually simplifies things.</li>
<li>Start a user group to empower other developers and designers.</li>
<li>Build tools that empower people.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2010/07/13/programming-and-practice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shrink Javascript with Diffable</title>
		<link>http://garrettbluma.com/2010/07/09/shrink-javascript-with-diffable/</link>
		<comments>http://garrettbluma.com/2010/07/09/shrink-javascript-with-diffable/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 18:57:51 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Optimization]]></category>

		<guid isPermaLink="false">http://garrettbluma.com/?p=281</guid>
		<description><![CDATA[It&#8217;s been some time since we&#8217;ve seen any new javascript minifiers out there. Google Closure was probably the most recent but many argue that was basically a re-hash of Yahoo&#8217;s YUI Compressor. This is something different. As web applications get better, there is more Javascript. Caching has been a big help to this—even though only [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been some time since we&#8217;ve seen any new javascript minifiers out there. <a href="http://code.google.com/closure/compiler/">Google Closure</a> was probably the most recent but many argue that was basically a re-hash of Yahoo&#8217;s <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>.</p>
<p><a href="http://www.stevesouders.com/blog/2010/07/09/diffable-only-download-the-deltas/">This is something different</a>.</p>
<p>As web applications get better, there is more Javascript.</p>
<p>Caching has been a big help to this—even though only <a href="http://www.yuiblog.com/blog/2007/01/04/performance-research-part-2/">effective for about 40-60% of your audience</a>. The problem with caching however, is that when a new version of the code is released the user must download all of it again.</p>
<p><a href="http://www.stevesouders.com/blog/2010/07/09/diffable-only-download-the-deltas/">Diffable JS</a> makes this less of an issue becuase the user might only need to download 10KB of changes instead of 200KB. It also sticks close to #1 rule of web developement: <a href="http://developer.yahoo.com/performance/rules.html">make browsers download as few files as possible</a>.</p>
<p>I think this project is awesome and I need to spend some time giving this a proper look-over.</p>
<p>Diffable JS: <a href="http://www.stevesouders.com/blog/2010/07/09/diffable-only-download-the-deltas/">http://www.stevesouders.com/blog/2010/07/09/diffable-only-download-the-deltas</a></p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2010/07/09/shrink-javascript-with-diffable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Joomla Sphinx Search Plugin</title>
		<link>http://garrettbluma.com/2010/02/16/joomla-sphinx-search-plugin/</link>
		<comments>http://garrettbluma.com/2010/02/16/joomla-sphinx-search-plugin/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 03:26:15 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[Joomla]]></category>
		<category><![CDATA[Web Programming]]></category>

		<guid isPermaLink="false">http://garrettbluma.com/?p=212</guid>
		<description><![CDATA[Beware, this is beta quality software. Use at your own risk. As we understand already, Joomla doesn&#8217;t have relevant searching. It&#8217;s a shame since everything else is designed well, but this is a problem regarding implementation. This article explains how to setup sphinx to index your Joomla articles and use my plugin to search using [...]]]></description>
			<content:encoded><![CDATA[<p class="dropshadow"><img class="alignnone size-full wp-image-218" title="sphinx-horse" src="http://garrettbluma.com/wp-content/uploads/2010/02/sphinx-horse.jpg" alt="" width="580" height="252" /></p>
<blockquote><p><strong>Beware, this is beta quality software. Use at your own risk.</strong></p></blockquote>
<p>As we understand already, Joomla doesn&#8217;t have relevant searching. It&#8217;s a shame since everything else is designed well, but this is a problem regarding implementation. This article explains how to setup sphinx to index your Joomla articles and use my plugin to search using Joomla.</p>
<p>In my own experiments I built a plugin that accomplished this. It works splendidly, and I had all intention of releasing the code to the public, but got distracted. This process is currently unrefined, but it works. I&#8217;m a fan of revision anyway, so if you see a way to improve this article, hit me up (email).</p>
<p><strong>So why doesn&#8217;t Joomla have relevant searching already?</strong> — Unfortunately it doesn&#8217;t seem like they had much choice about it. Joomla relies on MySQL. MySQL is just now beginning to get some Full-Text searching mechanisms implemented and those that do exist are spotty. For example, it is only available in recent versions of the MyISAM database engine and not at all for InnoDB. Plus, I&#8217;ve heard some complaints about it not even being terribly good at it&#8217;s own job.</p>
<p>A system like Sphinx can go beyond what MySQL supports anyway. It can use word stems and substitutions, so I could specify <tt>CPP</tt> to be used interchangeably with <tt>C++</tt> in any search query and it doesn&#8217;t get confused about plural or singular versions of words. It also supports weights, so I can tell Sphinx to prefer matches found in titles and move them higher in the search results.</p>
<h3>Install &amp; Configure Sphinx</h3>
<p>There are a number of good articles on the web about this. I may revisit how to install Sphinx in detail, but for now defer to the follow links:</p>
<ul>
<li><a href="http://www.sphinxsearch.com/docs/current.html#installation">Sphinx Homepage</a> — <em>Obviously the first place to start looking is the Sphinx homepage. Good documentation on Sphinx operation and internals.</em></li>
<li><a href="http://www.ibm.com/developerworks/library/os-php-sphinxsearch/">Build a custom search engine with PHP</a> — <em>IBM has a great article on using Sphinx in-the-field. This article describes setup of Sphinx as well as testing and integration with PHP.</em></li>
</ul>
<p>Here is my configuration I&#8217;ve been using for my Joomla Setup. This is basically the same as any configuration setup on IBM&#8217;s website, but adapted to Joomla. There are a few things you&#8217;ll need to edit though:</p>
<ul>
<li><tt>exampleuser</tt> — <em>This should be the username you connect with to search your database</em></li>
<li><tt>examplepass</tt> — <em>This should be the password for the username just described</em></li>
<li><tt>exampledb</tt> — <em>This is the database sphinx will be searching on.</em></li>
<li>Check your paths. I&#8217;m making some assumptions here. Your sphinx data should be outside of your web-root and readable/writable by whatever process <tt>searchd</tt> is running as.</li>
</ul>
<p><strong>/var/www/website/sphinx/config.conf:</strong></p>
<pre><code>
source mywebsite_articles
{
    type            = mysql
    sql_host        = localhost
    sql_user        = exampleuser
    sql_pass        = examplepassword
    sql_db          = exampledb
    sql_sock        = /var/run/mysqld/mysqld.sock
    sql_port        = 3306

    # indexer query
    # document_id MUST be the very first field
    # document_id MUST be positive (non-zero, non-negative)
    # document_id MUST fit into 32 bits
    # document_id MUST be unique

    sql_query = \
        SELECT `id`, `title`, `alias`, `introtext`, `fulltext`, `created`, `modified`, `hits` \
        FROM jos_content ;

    # document info query
    # ONLY used by search utility to display document information
    # MUST be able to fetch document info by its id, therefore
    # MUST contain '$id' macro
    #

    sql_query_info = \
        SELECT * \
        FROM jos_content  \
        WHERE id=$id
}
index mywebsite_articles
{
    source                  = mywebsite_articles
    path                    = /var/www/website/data
    morphology              = none

    min_word_len            = 3
    min_prefix_len          = 0
    min_infix_len           = 3
}

searchd
{
    port          = 3312
    log           = /var/www/website/sphinx/search.log
    query_log     = /var/www/website/sphinx/query.log
    pid_file      = /var/www/website/sphinx/searchd.pid
}
</code></pre>
<h3>Testing Sphinx</h3>
<p>How do we know if Sphinx is setup correctly? We test it!</p>
<p>First we need to generate the index. So fire up your terminal and run the following (assuming your sphinx install lives in /usr/local/sphinx):</p>
<pre><code>
/usr/local/sphinx/bin/indexer \
--config /var/www/website/sphinx/config.conf \
--all --rotate
</code></pre>
<p>Second we need to start the search daemon. This will process search requests.</p>
<pre><code>
/usr/local/sphinx/bin/searchd \
--config /var/www/website/sphinx/config.conf
</code></pre>
<p>If you get any errors, I&#8217;d recommend going back and reviewing the configuration and re-running the indexer, then start searchd again.</p>
<p>If we don&#8217;t have any errors, we can run a test outside of Joomla to see if everything is working correctly. For example:</p>
<pre><code>/usr/local/sphinx/bin/search \
--config /var/www/website/sphinx/config.conf \
"Hello world"</code></pre>
<h3>Install &amp; Configure Joomla Plugin</h3>
<p>You can download the plugin here (<a href="http://garrettbluma.com/track.php?file=http%3A%2F%2Fgarrettbluma.com/code/sphinx/plgSphinxContent-v1.zip">Download</a>) or at the bottom of this article.</p>
<p class="dropshadow"><img class="aligncenter size-full wp-image-231" title="Sphinx Plugin Upload" src="http://garrettbluma.com/wp-content/uploads/2010/02/Screen-shot-2010-02-16-at-6.49.47-PM.png" alt="Sphinx Plugin Upload" width="528" height="206" /></p>
<p>Enable the plugin. Be sure to turn off other search modules while you&#8217;re at it. It is much easier to determine if your search results are isolated to one plugin.</p>
<p class="dropshadow"><img class="aligncenter size-full wp-image-232" title="Enable Plugin" src="http://garrettbluma.com/wp-content/uploads/2010/02/Screen-shot-2010-02-16-at-6.50.51-PM.png" alt="Enable Plugin" /></p>
<p class="dropshadow"><img class="aligncenter size-full wp-image-235" title="Configure Sphinx Plugin" src="http://garrettbluma.com/wp-content/uploads/2010/02/Screen-shot-2010-02-16-at-6.52.43-PM.png" alt="Configure Sphinx Plugin" width="514" height="229" /></p>
<p>If you are hosting Sphinx on the same server as your web service, you&#8217;ll probably want to keep these similar to what I have. Otherwise, be sure to fill-in the appropriate fields here and configure any firewalls that may be between the web server and the Sphinx server.</p>
<p>You will also want to be careful to use the same name of your index defined in your config file. In my example I&#8217;m using <tt>mywebsite_articles</tt>. This is what I fill-in for <em>Resource Name.</em></p>
<h3>Test Sphinx Plugin</h3>
<p>The only thing left to do now is to actually test the thing. Go to your website and do a search!</p>
<h3>Completing the solution</h3>
<p>There are a few things still missing from this setup that I want you to be aware of.</p>
<p>First, if you don&#8217;t update your index periodically, you will only see the content that you indexed the first time. One solution is to setup a scheduled task (or cron) to re-index your content. Notice as well I put <tt>--rotate</tt> at the end of my indexing operation. Once Sphinx has updated the index, it will begin to use the new index to search with. You don&#8217;t need to restart your <tt>searchd</tt> process, just update the index.</p>
<p>Second, you should be aware that if your server restarts you&#8217;ll need <tt>searchd</tt> to start automatically. An init script would work great, even something as simple as this:</p>
<p><strong>/etc/init.d/searchd</strong></p>
<pre><code>
#! /bin/sh
NAME=sphinx
DAEMON=/usr/local/sphinx/bin/searchd
CONFIG=/var/www/website/sphinx/config.conf
[ -x "$DAEMON" ] || exit 0
case "$1" in
  start)
    echo "Stopping any running daemons..."
    $DAEMON --config $CONFIG --stop
    echo "Starting sphinx search daemon..."
    $DAEMON --config $CONFIG
    ;;
  stop)
    echo "Stopping sphinx search daemon..."
    $DAEMON --config $CONFIG --stop
    ;;
  *)
    echo "Usage: $NAME {start|stop}"
    exit 3
    ;;
esac
:
</code></pre>
<p><div class='download-link'>
							<a href='http://garrettbluma.com/track.php?file=http%3A%2F%2Fgarrettbluma.com/code/sphinx/plgSphinxContent-v2.zip'><img alt='Download' class='leftalign' src='http://garrettbluma.com/wp-content/plugins/dBeautifier/icons/tar.png' /></a>
							<h4>
								<a href='http://garrettbluma.com/track.php?file=http%3A%2F%2Fgarrettbluma.com/code/sphinx/plgSphinxContent-v2.zip'>plgSphinxContent-v2.zip (Sphinx Search Plugin)</a>
							</h4><p>Downloads: 7 File Size: 13.1 KB </p>
						</div></p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2010/02/16/joomla-sphinx-search-plugin/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Google Closure Review</title>
		<link>http://garrettbluma.com/2010/01/29/google-closure-review/</link>
		<comments>http://garrettbluma.com/2010/01/29/google-closure-review/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 02:03:15 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://garrettbluma.com/?p=189</guid>
		<description><![CDATA[So when Google released their Closure library almost three months ago I thought to myself: &#8220;Huh, that looks pretty cool. A modular, lightweight framework that has great UI tools. What&#8217;s not to love!?&#8221; I wanted then to write a post back then detailing how excited I was about it, but enough people wrote good pieces [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float: left; margin: 0 15px 15px 0;" src="/wp-content/uploads/2010/01/google-closure-logo.jpg" alt="Google Closure Logo" /></p>
<p>So when Google released their <a href="http://code.google.com/closure/library/">Closure library</a> almost three months ago I thought to myself:</p>
<blockquote class="orange"><p>&#8220;Huh, that looks pretty cool. A modular, lightweight framework that has great UI tools. What&#8217;s not to love!?&#8221;</p></blockquote>
<p>I wanted then to write a post back then detailing how excited I was about it, but enough people wrote good pieces early on ( <a href="http://www.sitepoint.com/blogs/2009/11/12/google-closure-how-not-to-write-javascript/">here</a>, <a href="http://googlecode.blogspot.com/2009/11/introducing-closure-tools.html">here</a>, and <a href="http://www.tripwiremagazine.com/2009/11/first-impressions-looking-into-google-closure-im-impressed.html">here</a>) and I didn&#8217;t want to add to the noise.</p>
<p>In the meantime, I decided to use Google&#8217;s Closure in one of my projects. I needed to build an RIA (Rich Internet Application) type website that needed to dynamically pull in a lot of data. Having gotten through most of that project I feel like I can substantiate a review of the framework.</p>
<h3>Great for UI, not so great for the basics</h3>
<p>I initially got exicited about Closure becuase of the quality of UI elements that Google was distributing with the API. I assumed that everything has this same level of abstraction from the nitty-gritty and would simplify my code.</p>
<p><em>The failings of Closure exist in the simple tasks not the complicated ones</em>, <a href="#html_insertion">adding HTML to the DOM</a>, <a href="#ajax_requests">doing an Ajax request</a>, and <a href="#selection">even element selection</a>. I&#8217;ll go into detail about each of these.</p>
<h3 id="html_insertion">HTML Insertion</h3>
<p>It&#8217;s easy to use <tt>element.innerHTML</tt>, but some work needs to be done to allow those added element to respond to events in all browsers. For example, IE6 will not register an event fired by an element created via <tt>innerHTML</tt>. If, however, that <tt>innerHTML</tt> is applied to an element outside the DOM and afterwards added via <tt>appendChild</tt>, then it works.</p>
<p>The following is a comparison of the same code:</p>
<p><strong>Raw Javascript (5 steps)</strong></p>
<pre><code class="javascript">
var html = "&lt;ul&gt;&lt;li&gt;a&lt;/li&gt;&lt;li&gt;b&lt;/li&gt;&lt;li&gt;c&lt;/li&gt;&lt;/ul&gt;";
var el = document.getElementById( 'id_of_element' );
var container = document.createElement( 'div' );
container.innerHTML = html;
el.appendChild( container );
</code></pre>
<p><strong>Google Closure (4 steps)</strong></p>
<pre><code class="javascript">
var html = "&lt;ul&gt;&lt;li&gt;a&lt;/li&gt;&lt;li&gt;b&lt;/li&gt;&lt;li&gt;c&lt;/li&gt;&lt;/ul&gt;";
var el = goog.dom.$('id_of_element');
var fragment = goog.dom.htmlToDocumentFragment( html );
el.appendChild( fragment );
</code></pre>
<p><strong>jQuery (2 steps)</strong></p>
<pre><code class="javascript">
$('#id_of_element').html(
    "&lt;ul&gt;&lt;li&gt;a&lt;/li&gt;&lt;li&gt;b&lt;/li&gt;&lt;li&gt;c&lt;/li&gt;&lt;/ul&gt;"
);
</code></pre>
<h3 id="ajax_requests">Doing an Ajax Request (specifically JSON):</h3>
<p>Here is a quick example of handling an Ajax request w/ some minor JSON validation. You don&#8217;t use <tt>eval()</tt> do you?</p>
<p><strong>Raw javascript</strong><small><em>To be fair I don&#8217;t know if this one works</em></small></p>
<pre><code class="javascript">
// Assumes we have a valid XmlHttp object via GetXmlHttpObject()
xmlHttp=GetXmlHttpObject();
xmlHttp.open("GET","form.php?format=json",true);
xmlHttp.onreadystatechange = function() {
    if (xmlHttp.readyState == 4) {
        var data = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
	    text.replace(/"(\\.|[^"\\])*"/g, ''))) &amp;&amp;
            eval('(' + text + ')');
        // …
    }
});
</code></pre>
<p><strong>Google Closure (4 steps)</strong></p>
<pre><code class="javascript">
goog.net.XhrIo.send( "form.php?format=json", function( event ) {
    if ( event.isSuccess() ) {
        var data = event.target.getResponseJson();
        // ...
    }
);
</code></pre>
<p><strong>jQuery (2 steps)</strong></p>
<pre><code class="javascript">
$.getJSON('form.php?format=json', function(data) {
    // ...
});
</code></pre>
<h3 id="selection">Element Selection</h3>
<p>I&#8217;ll admit, this is an unfair test since jQuery will always win this one. But the point is that <em>Google doesn&#8217;t even try to make this easier for the programmer</em>. Aside from some convenience functions there is nothing special. In my mind this proves the point that Google is much more focused on solving the complex problems and not the simple ones.</p>
<p><strong>Raw Javascript</strong></p>
<pre><code class="javascript">
var el = document.getElementById('id_of_element');
var myDivs = []; // … just not worth writing this by hand
</code></pre>
<p><strong>Google Closure</strong></p>
<pre><code class="javascript">
var el = goog.dom.$('id_of_element');
var myDivs = goog.dom.getElementsByTagNameAndClass('div','menu-item');
</code></pre>
<p><strong>jQuery</strong></p>
<pre><code class="javascript">
var el = $('#id_of_element');
var myDivs = $("div.menu-item");
</code></pre>
<h3>Conclusion</h3>
<p>It&#8217;s not that Google Closure is bad, it&#8217;s not. And don&#8217;t discredit it because I don&#8217;t want to use it. There are a ton of great applications for it and I am very happy they released it. The main issue as I see it, is that just isn&#8217;t designed for rapid development — a feature I put high emphasis on. I don&#8217;t want to downplay any of their hard work but from my perspective I don&#8217;t see as much value in it as I used to.</p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2010/01/29/google-closure-review/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Caching in Joomla 1.5 with Fault Tolerance</title>
		<link>http://garrettbluma.com/2009/12/20/programmatic-caching-in-joomla-1-5-with-fault-tolerance/</link>
		<comments>http://garrettbluma.com/2009/12/20/programmatic-caching-in-joomla-1-5-with-fault-tolerance/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 19:00:43 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[Joomla]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[Joomla 1.5]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.garrettbluma.com/?p=154</guid>
		<description><![CDATA[If you&#8217;ve used Joomla before, you may be aware that there are built-in caching features which you can activate to reduce the number of expensive database calls needed to render a page. This feature is also available to your own custom code, whether that be in the form of components, modules, or plugins. The actual [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://www.garrettbluma.com/images/posts/fault-tolerant-caching-overview.png" alt="Overview" /></p>
<p>If you&#8217;ve used Joomla before, you may be aware that there are built-in caching features which you can activate to reduce the number of expensive database calls needed to render a page. This feature is also available to your own custom code, whether that be in the form of components, modules, or plugins.</p>
<p>The actual mileage for this feature may vary due to the speed of the server and what Joomla decides to cache. Personally I think Joomla&#8217;s use of caching, specifically how they use it for articles, leaves something to be desired. The downsides include content that doesn&#8217;t get flushed out once it has changed or content that has too short of a lifetime to prove useful. Because of this, I don&#8217;t think lot of developers realize that you can use it to cache your own components, plugins, and modules reliably and without affecting the user experience in a negative way, all the while in a modest environment (i.e. a server environment that doesn&#8217;t have special software like memcached installed.)</p>
<p>You might consider implementing a little caching if:</p>
<ul>
<li>Your code is heavy and slow <em>(Don&#8217;t take it personally, mine is too sometimes)</em></li>
<li>Your code is high-latency requiring network resources that may or may not actually be available</li>
<li>You have a crazy number of visitors and your database is becoming a significant bottleneck</li>
</ul>
<p>In my own recent project I was able to improve my access times of some SOAP requests by 500% (~1 second/request down to ~200ms/request).</p>
<h3>Let&#8217;s get our bearings</h3>
<p style="text-align:center"><img src="http://www.garrettbluma.com/images/posts/fault-tolerant-caching-functions.png" alt="Overview" /></p>
<p>Here&#8217;s a basic example of some code which initializes a JCache object and get&#8217;s some data using it. You&#8217;ll notice that there are two functions, one which just generically gets some data <tt>getData</tt> and another function <tt>getDataCached</tt> which instantiates the cache and calls <tt>getData</tt>. We need to do this so that our cache is aware of what the inputs and outputs are, that way it can do a lookup on the cache and return data without ever touching <tt>getData</tt>. </p>
<p><strong>com_cachetest/cachetest.php:</strong></p>
<pre><code class="php">
class CacheTest {
    function getData($url) {
        // ... Get some data

        // in this case, I'm just returning some dummy data instead of
        // downloading a web page which if we plan for the worst case scenario,
        // might not be available.

        $data = $url;

        // send data back
        return $data;
    }
    function getDataCached($url) {

        $group = "cachetest";
        $function = array("CacheTest", "getData");

        // get a cache object and name it something useful
        $cache =&amp; JFactory::getCache( $group );
        $cache->setCaching( 1 ); // enable caching (1 = enabled, 0 = disabled)

        // call our function "getData" through the cache
        $result = $cache->call( $function , $url);

        return $result;
    }
}

$data = CacheTest::getDataCached( "http://example.com" );
var_dump($data); // to see what we actually get
</code></pre>
<h3>Fault Tolerant Caching</h3>
<p>One issue in the above example is that if <tt>getData</tt> returns some bogus data, it&#8217;s going to be stuck in the cache and you won&#8217;t realize it until it&#8217;s too late. This isn&#8217;t a likely scenario for a quick database call but if you have a network request that is waiting and waiting and eventually reaches timeout, the cached data will possibly be empty. This can be problematic but it&#8217;s also easily avoided. In the following example we do a quick check to see if the data is invalid, remove the old data and get a fresh copy. </p>
<p><strong>com_cachetest/cachetest.php:</strong></p>
<pre><code class="php">
class CacheTest {
    function getData($url) {
        // ... Get some data

        // in this case, I'm just returning some dummy data instead of
        // downloading a web page which if we plan for the worst case scenario,
        // might not be available.

        $data = $url;

        // send data back
        return $data;
    }

    function getDataCached($url) {

        $group = "cachetest";
        $function = array("CacheTest", "getData");

        // get a cache object and name it something useful
        $cache =&amp; JFactory::getCache( $group );
        $cache->setCaching( 1 ); // enable caching (1 = enabled, 0 = disabled)

        // call our function "getData" through the cache
        $result = $cache->call( $function, $url);

        // Check if we get sane data. Depending on your data this
        // could be more than just an empty check
        if ( empty( $result ) ) {

            // find the id to remove data for
            $id = $cache->_makeId( $function, $url );

            // invalidate this entry in the cache
            $cache->remove( $id, $group );

            // call our function again knowing the cache has been fixed
            $result = $cache->call( $function, $url );
        }
        return $result;
    }
}
$data = CacheTest::getDataCached( "http://example.com" );
var_dump($data); // to see what we actually get
</code></pre>
<h3>In Closing</h3>
<p>Joomla&#8217;s caching API is simple and, by default, just writes these cache files to disk. Although not the fastest approach the default options are really handy for a less-than-stellar server setup. These caching options are available to even shared hosts. At the same time, I should mention that Joomla has done a fantastic job of integrating support for more advanced caching systems like <a href="http://memcached.org/">memcache</a> and <a href="http://xdebug.org/">xdebug</a> so that the above code can be run even faster without any modifications.</p>
<p><div class='download-link'>
							<a href='http://garrettbluma.com/track.php?file=http%3A%2F%2Fgithub.com/gbluma/joomla-caching-example/tree/master/.git'><img alt='Download' class='leftalign' src='http://garrettbluma.com/wp-content/plugins/dBeautifier/icons/github.png' /></a>
							<h4>
								<a href='http://garrettbluma.com/track.php?file=http%3A%2F%2Fgithub.com/gbluma/joomla-caching-example/tree/master/.git'>joomla-caching-example.git (Programmatic Caching in Joomla 1.5 with Fault Tolerance)</a>
							</h4><p>Downloads: 64 File Size: 0.0 KB </p>
						</div></p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2009/12/20/programmatic-caching-in-joomla-1-5-with-fault-tolerance/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Too Much Noise</title>
		<link>http://garrettbluma.com/2009/08/19/too-much-nois/</link>
		<comments>http://garrettbluma.com/2009/08/19/too-much-nois/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 17:13:35 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://www.garrettbluma.com/2009/08/19/why-i-hate-the-wordpress-community/</guid>
		<description><![CDATA[The WordPress community bugs me sometimes. I don&#8217;t really have anything bad to say about the community personally. Just the side-effects of the community, which I can sum up in one word. NOISE. There are tens-of-thousands of people posting blog posts about the same exact thing. For example, recently I needed to write a plugin [...]]]></description>
			<content:encoded><![CDATA[<p>The WordPress community bugs me sometimes. I don&#8217;t really have anything bad to say about the community personally. Just the side-effects of the community, which I can sum up in one word.</p>
<p>NOISE.</p>
<p>There are tens-of-thousands of people posting blog posts about the same exact thing. For example, recently I needed to write a plugin that would display the results of a search on a page in the content area. I looked it up on google and found thousands of articles on &#8220;How to write a wordpress plugin&#8221;. Each one describing in nearly the EXACT same words how to accomplish the very first step in writing a widget (and only a widget&#8230; certainly no-one would want to write something ELSE!) Nothing more. I was only able to get some success after reading the source code of about 15 other plugins.</p>
<p>While working on a different wordpress site, I was looking for some ways to save time and use a plugin I was SURE someone had made (something that could rename page titles in the menu). But again there are tens-of-thousands of people posting articles on &#8220;The top 10 plugins to save you time&#8221; and &#8220;The 20 plugins every wordpress developer should know about!&#8221; Maybe I&#8217;m being a little nieve that there are actually people who would be stupid enough to title ther articles that way and actually have USEFUL content. Silly me.</p>
<p>Before I accumulate too many haters though I should validate that WordPress is a good system. I like it. In fact, it seems to be the BEST platform for SEO related functionality and it fits the blog role very well. The themes are funky but there are a lot of options out there and the plugin library is vast, if misleading.</p>
<p>Do the community a favor next time you post an article about your favorite tool. Ask yourself this question &#8220;Is this article helpful or am I just adding to the noise?&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2009/08/19/too-much-nois/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IE Caching Ajax Requests When It Shouldn&#8217;t</title>
		<link>http://garrettbluma.com/2009/08/17/ie-caching-ajax-requests-when-it-shouldnt/</link>
		<comments>http://garrettbluma.com/2009/08/17/ie-caching-ajax-requests-when-it-shouldnt/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 18:09:21 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[Web Programming]]></category>

		<guid isPermaLink="false">http://www.garrettbluma.com/?p=136</guid>
		<description><![CDATA[I&#8217;ve noticed some difficulty in Ajax controls not working correctly in IE (any version). This may be old news for many of you, but I&#8217;m going to post it anyway—hopefully someone will use it. The Problem: Ajax requests don&#8217;t seem to be working in IE, but there aren&#8217;t any error messages and nothing fails like [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve noticed some difficulty in Ajax controls not working correctly in IE (any version). This may be old news for many of you, but I&#8217;m going to post it anyway—hopefully someone will use it.</p>
<p><strong>The Problem:</strong></p>
<p>Ajax requests don&#8217;t seem to be working in IE, but there aren&#8217;t any error messages and nothing fails like you&#8217;d expect it to—the only real issue is that the content is not updating. Everything works as expected in Firefox, Safari, Chrome, etc.</p>
<p><strong>The Solution:</strong></p>
<p>This problem is because IE has aggressive caching in place for Ajax requests. This is bad. Why is this bad? Because we commonly use Ajax to refresh content and make updates to our data. Unless we make some updates to our code, we will see stale information and mislead our visitors.</p>
<p>We can fix this pretty easily though. Some people claim that by switching our GET requests to POST that we&#8217;ll solve the problem at hand. I didn&#8217;t have any luck with that. Instead if you assign a header explicitly telling the browser to invalidate the page after viewing it, you can prevent IE from caching the page.</p>
<p>In PHP you do it like this:</p>
<div>
<div><code><span style="color: #000000;"> <span style="color: #0000bb;">&lt;?php<br />
header</span><span style="color: #007700;">(</span><span style="color: #dd0000;">"Cache-Control: no-cache, must-revalidate"</span><span style="color: #007700;">); </span><span style="color: #ff8000;"><br />
</span><span style="color: #0000bb;">header</span><span style="color: #007700;">(</span><span style="color: #dd0000;">"Expires: Sat, 26 Jul 1997 05:00:00 GMT"</span><span style="color: #007700;">); </span><span style="color: #ff8000;">// Date in the past<br />
</span><span style="color: #0000bb;">?&gt;</span> </span> </code></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2009/08/17/ie-caching-ajax-requests-when-it-shouldnt/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>MacBook Wireless Problems Caused by 10.5.8 Update</title>
		<link>http://garrettbluma.com/2009/08/12/macbook-wireless-problems-caused-by-10-5-8-update/</link>
		<comments>http://garrettbluma.com/2009/08/12/macbook-wireless-problems-caused-by-10-5-8-update/#comments</comments>
		<pubDate>Wed, 12 Aug 2009 16:38:24 +0000</pubDate>
		<dc:creator>Garrett Bluma</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[AirPort]]></category>
		<category><![CDATA[MacBook]]></category>
		<category><![CDATA[Wireless]]></category>

		<guid isPermaLink="false">http://www.garrettbluma.com/2009/08/12/macbook-wireless-problems-caused-by-10-5-8-update/</guid>
		<description><![CDATA[Problem: Built-in wireless on MacBook (and possibly MacBook Pro) is unable to connect to any wireless devices following an update to OS X (10.5.8 &#8212; released Aug 5, 2009) Connection issues include not being able to connect to a wireless network (&#8220;Connection Timeout&#8221;) and high amounts of packet loss. Solution: Apple released a patch to [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Problem: </strong></p>
<p>Built-in wireless on MacBook (and possibly  MacBook Pro) is unable to connect to any wireless devices following an update to OS X (10.5.8 &#8212; released Aug 5, 2009)</p>
<p>Connection issues include not being able to connect to a wireless network (&#8220;Connection Timeout&#8221;) and high amounts of packet loss.</p>
<p><strong>Solution:</strong></p>
<p>Apple released a patch to fix this issue, just run software update (in System Preferences) and make sure you install the package that is like &#8220;AirPort performance while on battery power&#8221;. This will undo the bug they introduced in the 10.5.8.</p>
<p>That did it for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://garrettbluma.com/2009/08/12/macbook-wireless-problems-caused-by-10-5-8-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.568 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2010-08-30 08:09:02 -->
<!-- Compression = gzip -->