<?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>CB1, INC. &#187; uncategorized</title>
	<atom:link href="http://www.cb1inc.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cb1inc.com</link>
	<description></description>
	<lastBuildDate>Wed, 28 Sep 2011 17:54:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Meet the RotatorContainer</title>
		<link>http://www.cb1inc.com/2008/04/25/meet-the-rotatorcontainer/</link>
		<comments>http://www.cb1inc.com/2008/04/25/meet-the-rotatorcontainer/#comments</comments>
		<pubDate>Fri, 25 Apr 2008 23:27:44 +0000</pubDate>
		<dc:creator>Chris Barber</dc:creator>
				<category><![CDATA[dojo]]></category>
		<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I've been sitting on this code for a while and decided to clean it up and submit it to the <a href="http://dojotoolkit.org">Dojo Javascript Toolkit</a>.

The RotatorContainer cycles through <code>dijit.layout.ContentPane</code>s and provides navigation in the form of tabs or a pager.  There a number of timing settings you can adjust as well as the layout of the controls.

<div align="center"><img src="http://www.cb1inc.com/sites/default/blog/20080425-rotator.png"/></div>

<a href="http://www.cb1inc.com/dojo-1.1.0-build/dojox/layout/tests/test_RotatorContainer.html">Give it a try!</a>  You can also see it in action on the front page of <a href="http://www.cb1inc.com">http://www.cb1inc.com</a>.

I <a href="http://trac.dojotoolkit.org/ticket/6612">submitted this widget</a>, so it may or may not be accepted.  In the meantime, you can download the RotatorContainer here: <a href="http://www.cb1inc.com/sites/default/RotatorContainer.tar.gz">RotatorContainer.tar.gz</a> [9KB] To install it, extract it into your dijit's parent directory.

Here's how you can use it:

<pre><code>&#60;script type="text/javascript"&#62;
dojo.require("dojo.parser");
dojo.require("dijit.layout.ContentPane");
dojo.require("dojox.layout.RotatorContainer");
&#60;/script&#62;

&#60;div dojoType="dojox.layout.RotatorContainer" id="myRotator" showTabs="true"
      autoStart="true" transitionDelay="5000"&#62;
    &#60;div dojoType="dijit.layout.ContentPane" title="1"&#62;
        Pane 1!
    &#60;/div&#62;
    &#60;div dojoType="dijit.layout.ContentPane" title="2"&#62;
        Pane 2!
    &#60;/div&#62;
    &#60;div dojoType="dijit.layout.ContentPane" title="3"&#62;
        Pane 3!
    &#60;/div&#62;
&#60;/div&#62;
</code></pre>

NOTE: There is some CSS needed to make the RotatorContainer look correct.  Include or copy the contents of the <a href="http://www.cb1inc.com/dojo-1.1.0/dojox/layout/resources/RotatorContainer.css">dijit/layout/resources/RotatorContainer.css</a> into your CSS file.

The magic happens once you have some content.  It takes a bit of time to tweak things, but you can pretty much do anything you can imagine.

The RotatorContainer can be controlled by a pager which includes a play/pause button, next and previous button, and the current and total panes.  You can also have as many pagers as you'd like.  The pager code looks like this:

<pre><code>&#60;script type="text/javascript"&#62;
dojo.require("dijit.form.Button");
&#60;/script&#62;

&#60;div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
    &#60;button dojoType="dijit.form.Button" dojoAttachPoint="previous"&#62;Prev&#60;/button&#62;
    &#60;button dojoType="dijit.form.ToggleButton" dojoAttachPoint="playPause"&#62;&#60;/button&#62;
    &#60;button dojoType="dijit.form.Button" dojoAttachPoint="next"&#62;Next&#60;/button&#62;
    &#60;span dojoAttachPoint="current"&#62;&#60;/span&#62; / &#60;span dojoAttachPoint="total"&#62;&#60;/span&#62;
&#60;/div&#62;
</code></pre>

One thing I should note, if this widget should find it's way into dojox, it's possible the name or functionality will change.

If time permitted, I would have liked to add additional transitions such as a left-to-right wipe.  Oh well.

Enjoy!]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been sitting on this code for a while and decided to clean it up and submit it to the <a href="http://dojotoolkit.org">Dojo Javascript Toolkit</a>.</p>
<p>The RotatorContainer cycles through <code>dijit.layout.ContentPane</code>s and provides navigation in the form of tabs or a pager.  There a number of timing settings you can adjust as well as the layout of the controls.</p>
<div align="center"><img src="/wp-content/uploads/2009/12/20080425-rotator1.png"/></div>
<p><a href="http://download.dojotoolkit.org/release-1.2.0/dojo-release-1.2.0/dojox/layout/tests/test_RotatorContainer.html">Give it a try!</a></p>
<p>Here&#8217;s how you can use it:</p>
<pre class="brush: xml; title: ;">
&lt;script type=&quot;text/javascript&quot;&gt;
dojo.require(&quot;dojo.parser&quot;);
dojo.require(&quot;dijit.layout.ContentPane&quot;);
dojo.require(&quot;dojox.layout.RotatorContainer&quot;);
&lt;/script&gt;

&lt;div dojoType=&quot;dojox.layout.RotatorContainer&quot; id=&quot;myRotator&quot; showTabs=&quot;true&quot;
      autoStart=&quot;true&quot; transitionDelay=&quot;5000&quot;&gt;
    &lt;div dojoType=&quot;dijit.layout.ContentPane&quot; title=&quot;1&quot;&gt;
        Pane 1!
    &lt;/div&gt;
    &lt;div dojoType=&quot;dijit.layout.ContentPane&quot; title=&quot;2&quot;&gt;
        Pane 2!
    &lt;/div&gt;
    &lt;div dojoType=&quot;dijit.layout.ContentPane&quot; title=&quot;3&quot;&gt;
        Pane 3!
    &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>NOTE: There is some CSS needed to make the RotatorContainer look correct.  Include or copy the contents of the <a href="http://download.dojotoolkit.org/release-1.2.0/dojo-release-1.2.0/dojox/layout/resources/RotatorContainer.css">dojox/layout/resources/RotatorContainer.css</a> into your CSS file.</p>
<p>The magic happens once you have some content.  It takes a bit of time to tweak things, but you can pretty much do anything you can imagine.</p>
<p>The RotatorContainer can be controlled by a pager which includes a play/pause button, next and previous button, and the current and total panes.  You can also have as many pagers as you&#8217;d like.  The pager code looks like this:</p>
<pre class="brush: xml; title: ;">
&lt;script type=&quot;text/javascript&quot;&gt;
dojo.require(&quot;dijit.form.Button&quot;);
&lt;/script&gt;

&lt;div dojoType=&quot;dojox.layout.RotatorPager&quot; rotatorId=&quot;myRotator&quot;&gt;
    &lt;button dojoType=&quot;dijit.form.Button&quot; dojoAttachPoint=&quot;previous&quot;&gt;Prev&lt;/button&gt;
    &lt;button dojoType=&quot;dijit.form.ToggleButton&quot; dojoAttachPoint=&quot;playPause&quot;&gt;&lt;/button&gt;
    &lt;button dojoType=&quot;dijit.form.Button&quot; dojoAttachPoint=&quot;next&quot;&gt;Next&lt;/button&gt;
    &lt;span dojoAttachPoint=&quot;current&quot;&gt;&lt;/span&gt; / &lt;span dojoAttachPoint=&quot;total&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
</pre>
<p>One thing I should note, if this widget should find it&#8217;s way into dojox, it&#8217;s possible the name or functionality will change.</p>
<p>If time permitted, I would have liked to add additional transitions such as a left-to-right wipe.  Oh well.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cb1inc.com/2008/04/25/meet-the-rotatorcontainer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MethodSelectionException When Invoking Java From ColdFusion MX</title>
		<link>http://www.cb1inc.com/2007/06/14/methodselectionexception-when-invoking-java-from-coldfusion-mx/</link>
		<comments>http://www.cb1inc.com/2007/06/14/methodselectionexception-when-invoking-java-from-coldfusion-mx/#comments</comments>
		<pubDate>Thu, 14 Jun 2007 17:50:16 +0000</pubDate>
		<dc:creator>Chris Barber</dc:creator>
				<category><![CDATA[coldfusion]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[In ColdFusion MX, you can create a Java object by calling the handy <a href="http://livedocs.adobe.com/coldfusion/6.1/htmldocs/functi42.htm#wp1102241" target="_blank"><code>CreateObject()</code></a> function.

<pre>&#60;CFSET myObj = CreateObject("java", "java.util.Hashtable")&#62;</pre>

Suppose you have the following Java class:

<div class="cb1-docs-code"><pre>class Person {
    private String name;

    public void setName(String n) {
       this.name = n;
    }
}</pre></div>

Now, let's create an instance in ColdFusion and set a name:

<div class="cb1-docs-code"><pre>&#60;CFSET somebodySpecial = CreateObject("java", "Person")&#62;
&#60;CFSET somebodySpecial.setName("Chuck")&#62;</pre></div>

Cool, but what happens if you pass an argument that isn't a string:

<div class="cb1-docs-code"><pre>&#60;CFSET somebodySpecial.setName(123)&#62;

coldfusion.runtime.java.MethodSelectionException:
    The selected method setName was not found.</pre></div>

Whoops!  ColdFusion wasn't able to find a method of <code>Person</code> with a signature of "<code>public void setName(int)</code>".  What you need to do is cast the arguments to the correct datatype.  For this example, you could do something like this:

<div class="cb1-docs-code"><pre>&#60;CFSET somebodySpecial.setName(ToString(123))&#62;</pre></div>

The problem is what if you need to call methods that use other data types such as int, double, or boolean.  <code>ToString()</code> won't cut it.  Instead use ColdFusion's <a href="http://livedocs.adobe.com/coldfusion/6.1/htmldocs/funct147.htm" target="_blank"><code>JavaCast()</code></a> function:

<div class="cb1-docs-code"><pre>JavaCast(type, variable)

type        "boolean"
            "int"
            "long"
            "float"
            "double"
            "String"

variable    A ColdFusion variable that holds a scalar or string type
</pre></div>

So, the correct way is:

<div class="cb1-docs-code"><pre>&#60;CFSET somebodySpecial.setName(JavaCast("String", 123))&#62;
&#60;CFSET somebodySpecial.setName(JavaCast("String", "Chuck"))&#62;</pre></div>

No more MethodSelectionExceptions!]]></description>
			<content:encoded><![CDATA[<p>In ColdFusion MX, you can create a Java object by calling the handy <a href="http://livedocs.adobe.com/coldfusion/6.1/htmldocs/functi42.htm#wp1102241" target="_blank"><code>CreateObject()</code></a> function.</p>
<pre class="brush: xml; title: ;">
&lt;CFSET myObj = CreateObject(&quot;java&quot;, &quot;java.util.Hashtable&quot;)&gt;
</pre>
<p>Suppose you have the following Java class:</p>
<pre class="brush: java; title: ;">
class Person {
    private String name;

    public void setName(String n) {
       this.name = n;
    }
}
</pre>
<p>Now, let&#8217;s create an instance in ColdFusion and set a name:</p>
<pre class="brush: xml; title: ;">
&lt;CFSET somebodySpecial = CreateObject(&quot;java&quot;, &quot;Person&quot;)&gt;
&lt;CFSET somebodySpecial.setName(&quot;Chuck&quot;)&gt;
</pre>
<p>Cool, but what happens if you pass an argument that isn&#8217;t a string:</p>
<pre class="brush: xml; title: ;">
&lt;CFSET somebodySpecial.setName(123)&gt;
</pre>
<pre class="brush: plain; title: ;">
coldfusion.runtime.java.MethodSelectionException:
    The selected method setName was not found.
</pre>
<p>Whoops!  ColdFusion wasn&#8217;t able to find a method of <code>Person</code> with a signature of &#8220;<code>public void setName(int)</code>&#8220;.  What you need to do is cast the arguments to the correct datatype.  For this example, you could do something like this:</p>
<pre class="brush: xml; title: ;">
&lt;CFSET somebodySpecial.setName(ToString(123))&gt;
</pre>
<p>The problem is what if you need to call methods that use other data types such as int, double, or boolean.  <code>ToString()</code> won&#8217;t cut it.  Instead use ColdFusion&#8217;s <a href="http://livedocs.adobe.com/coldfusion/6.1/htmldocs/funct147.htm" target="_blank"><code>JavaCast()</code></a> function:</p>
<pre class="brush: plain; title: ;">
JavaCast(type, variable)

type        &quot;boolean&quot;
            &quot;int&quot;
            &quot;long&quot;
            &quot;float&quot;
            &quot;double&quot;
            &quot;String&quot;

variable    A ColdFusion variable that holds a scalar or string type
</pre>
<p>So, the correct way is:</p>
<pre class="brush: xml; title: ;">
&lt;CFSET somebodySpecial.setName(JavaCast(&quot;String&quot;, 123))&gt;
&lt;CFSET somebodySpecial.setName(JavaCast(&quot;String&quot;, &quot;Chuck&quot;))&gt;
</pre>
<p>No more MethodSelectionExceptions!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cb1inc.com/2007/06/14/methodselectionexception-when-invoking-java-from-coldfusion-mx/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>OSCON 2007</title>
		<link>http://www.cb1inc.com/2007/05/31/oscon-2007/</link>
		<comments>http://www.cb1inc.com/2007/05/31/oscon-2007/#comments</comments>
		<pubDate>Thu, 31 May 2007 16:02:53 +0000</pubDate>
		<dc:creator>Chris Barber</dc:creator>
				<category><![CDATA[oscon]]></category>
		<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I'm packing my bags and heading to <a href="http://conferences.oreillynet.com/os2007/" target="_blank">OSCON</a>: the open source conference sponsored by O'Reilly.  The conference is held July 23rd - 27th in Portland, OR.

<div align="center"><a href="http://conferences.oreillynet.com/os2007/" target="_blank"><img alt="OSCON" src="http://cb1inc.com/sites/default/blog/20070531-oscon.png"></a></div>
This will be my first time going to OSCON.  It was a tough decision because there were some other conferences I wouldn't have mind going to.

The first two days of the conferences, Monday and Tuesday, are tutorial days.  They cost extra, but you get 3-1/2 hours of exposure.  I've decided I'm going to the following tutorials:
<ul><li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/12829" target="_blank">Pthreads programming: a hands-on introduction</a></li><li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/12174" target="_blank">Linux performance monitoring</a></li><li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/13163" target="_blank">New parallel programming tools for a multicore world</a></li><li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/13088" target="_blank">Next-gen interaction with Ajax, Comet, and PHP</a></li></ul>There are a couple others that sound interesting, I have decided to focus on content that is applicable to the direction CB1 is heading.

Early bird discounts end Monday, June 4th, so you'd better <a href="http://conferences.oreillynet.com/pub/w/58/register.html" target="_blank">register today</a>.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m packing my bags and heading to <a href="http://conferences.oreillynet.com/os2007/" target="_blank">OSCON</a>: the open source conference sponsored by O&#8217;Reilly.  The conference is held July 23rd &#8211; 27th in Portland, OR.</p>
<div align="center"><a href="http://conferences.oreillynet.com/os2007/" target="_blank"><img alt="OSCON" src="/wp-content/uploads/2009/12/20070531-oscon.png"></a></div>
<p>This will be my first time going to OSCON.  It was a tough decision because there were some other conferences I wouldn&#8217;t have mind going to.</p>
<p>The first two days of the conferences, Monday and Tuesday, are tutorial days.  They cost extra, but you get 3-1/2 hours of exposure.  I&#8217;ve decided I&#8217;m going to the following tutorials:</p>
<ul>
<li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/12829" target="_blank">Pthreads programming: a hands-on introduction</a></li>
<li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/12174" target="_blank">Linux performance monitoring</a></li>
<li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/13163" target="_blank">New parallel programming tools for a multicore world</a></li>
<li><a href="http://conferences.oreillynet.com/cs/os2007/view/e_sess/13088" target="_blank">Next-gen interaction with Ajax, Comet, and PHP</a></li>
</ul>
<p>There are a couple others that sound interesting, I have decided to focus on content that is applicable to the direction CB1 is heading.</p>
<p>Early bird discounts end Monday, June 4th, so you&#8217;d better <a href="http://conferences.oreillynet.com/pub/w/58/register.html" target="_blank">register today</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cb1inc.com/2007/05/31/oscon-2007/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blocking IPs on Drupal 5.x</title>
		<link>http://www.cb1inc.com/2007/05/11/blocking-ips-on-drupal-5-x/</link>
		<comments>http://www.cb1inc.com/2007/05/11/blocking-ips-on-drupal-5-x/#comments</comments>
		<pubDate>Fri, 11 May 2007 05:33:07 +0000</pubDate>
		<dc:creator>Chris Barber</dc:creator>
				<category><![CDATA[drupal]]></category>
		<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Recently, this site ran into some problems with comment spammers.  In order to stop this, I needed to block their IP address to prevent them from posting bogus comments.

Begin by logging into Drupal and navigating to:
<div class="cb1-docs-code"><pre>Administer &#62; User management &#62; Access rules</pre></div>
Click "Add Rule" and enter the following information:
<ul>
<li>Access type: Deny</li>
<li>Rule type: Host</li>
<li>Mask: &#60;IP address to block&#62;</li>
</ul>
Add the rule and the user should be blocked.  If you want to block entire class of IP addresses, you can use a '%' such as "xxx.xxx.xxx.%".]]></description>
			<content:encoded><![CDATA[<p>Recently, this site ran into some problems with comment spammers.  In order to stop this, I needed to block their IP address to prevent them from posting bogus comments.</p>
<p>Begin by logging into Drupal and navigating to:</p>
<pre><code>Administer &gt; User management &gt; Access rules</code></pre>
<p>Click &#8220;Add Rule&#8221; and enter the following information:</p>
<ul>
<li>Access type: Deny</li>
<li>Rule type: Host</li>
<li>Mask: &lt;IP address to block&gt;</li>
</ul>
<p>Add the rule and the user should be blocked.  If you want to block entire class of IP addresses, you can use a &#8216;%&#8217; such as &#8220;xxx.xxx.xxx.%&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cb1inc.com/2007/05/11/blocking-ips-on-drupal-5-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scalability and Performance Best Practices</title>
		<link>http://www.cb1inc.com/2007/04/24/scalability-and-performance-best-practices/</link>
		<comments>http://www.cb1inc.com/2007/04/24/scalability-and-performance-best-practices/#comments</comments>
		<pubDate>Tue, 24 Apr 2007 23:43:13 +0000</pubDate>
		<dc:creator>Chris Barber</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Here at the <a href="http://www.mysqlconf.com" target="_blank">MySQL Conference and Expo</a>, Laura Thomson gave a great talk about Scalability and Performance Best Practices.

She had some interesting points about scalability. She basically said that no matter what language you write your web application, whether it's compiled (C/C++) or interpreted (PHP, Java), you are subject to scalability issues. Another potential problem is optimizing before you know what exactly to optimize. This can lead to a loss of time that could have been spent on more important things.

Laura's talk covers three types of best practices: general, scalability, and performance.

<b>General Best Practices</b>
First tip is to profile early and profile often. The earlier you can detect poor performance, the easier it is to fix. There are a handful of tools (<a href="http://pecl.php.net/package/apd" target="_blank">APD</a>, <a href="http://xdebug.org" target="_blank">Xdebug</a>, <a href="http://framework.zend.com" target="_blank">Zend</a>) that can help with profiling. Use system profiling tools such as <a href="http://sourceforge.net/projects/strace" target="_blank">strace</a>, <a href="http://www.sun.com/bigadmin/content/dtrace" target="_blank">dtrace</a>, and <a href="http://packages.debian.org/unstable/utils/ltrace.html" target="_blank">ltrace</a> to gather more information.

There are two types of effective profiling: debugging and habitual. Debugging profiling is about spotting deviations from the norm and habitual profiling is making the norm better. Profiling is an art and requires lots of practice to know where to look.

It is essential that the IT admins and the developers cooperate. This allows crisis' to be handled properly, especially in production environments were outages are time critical. Team members should report alert the developers of any abnormal behavior changes after a new code release is pushed. Before pushing new code, schedule a launch window and procedures for having developers fix problems and possibly falling back to a previous version. Avoid pushing releases on Fridays, otherwise key team members may be unavailable or over worked on the weekend.

It is recommended to test your application with production data. Test data may not take into account certain scenarios where bugs can be introduced. It is advised to have a staging environment which uses production data and also undergoes simulated load testing.

In order for you to track your application's performance, you should record your applications performance over a period of time, then analyze the data to find potential issues. There are several means of tracking performance including access logs, system metrics, application profiling, and query profiling.

When a problem occurs, don't make assumptions. The problem may be caused by something other than what you think it might be.

<b>Scalability Best Practices</b>
When the web application begins to suffer performance issues, start to decouple and isolate components to track down the source. If you need to tweak code, spend only enough time to refactor as needed. Reduce load on servers by moving static content on to dedicated servers.

By default, PHP stores session data on the hard drive. This can cause performance issues and can benefit from storing the session data in a database or better yet in a distributed cache such as <a href="http://www.danga.com/memcached" target="_blank">memcached</a>.

The most important thing you can do to improve performance is to cache as much data as possible. There are many levels of caching. You can cache data sets or precomputed fragments. For things like images, you can set up dedicated services for caching and serving static content. The usual suspects are recommended for caching (APC, memcached, <a href="http://www.squid-cache.org" target="_blank">Squid</a>).

PHP out of the box does not cache compiled pages. That means that ever request, each page has to be parsed and executed. Extensions such as APC and Zend can cache the compiled pages for an immediate speed improvement.

MySQL's query cache works, but isn't necessarily implemented the best way. If you query a table, the results are cached on the MySQL server. If a row is inserted, updated, or deleted, the entire cache is flushed. This supposedly has been fixed in MySQL 5.1, but a setting has to be set to not flush the cache.

To scale, your data can be federated across multiple MySQL servers. There can be complications with regards to data reliability and table joins can suffer from major speed hits.

A more reliable way to scale is to use replication. Replication does suffer from "slave lag" issues. The reason the lag can be high is because the master server uses multiple threads to store the data locally. The slave server has to process the replicated items in a single threaded mode to ensure the order of which the transactions is preserved. You can display the status of MySQL's I/O and SQL thread by executing a <code>SHOW PROCESSLIST</code> statement.

The more database writes, the greater the lag. Depending on your application, you may only want to use replication for failover or backups.

Sometimes you may benefit from designing your application to avoid situations where data is hard to scale and can't easily be cached.

<b>Performance Best Practices</b>
You definitely want to use a compiler cache. As described above, use APC or Zend for PHP5. If you are connecting to an external data source, perhaps a web service or data feed, minimize the number of instances you request them. Cache their response if possible. You may be able to load the data dynamically using Javascript and a little Ajax magic. Maybe the data isn't a must have or maybe you can have a page dedicated to display the 3rd party data.

When tuning your applications performance, change one thing at a time. If you change more than one thing, how do you know which change caused the improvement and how do you know if you didn't introduce new bugs changing the other things. Use MySQL's EXPLAIN statement to profile your queries and enable the slow query logging. Use <a href="http://jeremy.zawodny.com/mysql/mytop" target="_blank">MyTop</a> or <a href="http://sourceforge.net/projects/innotop" target="_blank">InnoTop</a> to help profile your queries.

It is crucial that your database is properly indexed. If a table has poorly designed indexes or perhaps too many indexes. Use the smallest data type possible and try to design your tables to be fixed width. That means, use char instead of varchar, set the length of your fields to logical lengths (ie use 128 chars instead of 107 chars). De-normalize when necessary. Remove static data out of the database or store it in a MEMORY table. Use the appropriate storage engine for each table.

For your queries, minimize the number of queries and cache them outside the database when possible.

She claims that deeply recursive code is expensive in PHP. Make sure you are not doing unnecessary looping. If you find that you are, chances are you are doing something wrong and that there is a better idiom for performing the task.

Don't try to work around or re-write perceived inefficiencies in PHP. Use regular expressions to do intense string manipulation. instead of writing complex serialization code, use PHP's extensions to do the heavy lifting. Before spending time to write some boilerplate function, check to see if there are any extensions that exist that could help save you time.

Laura gave this talk on behalf of George Schlossnagle. George's original presentation can be found at <a href="http://omniti.com/~george/talks" target="_blank">http://omniti.com/~george/talks</a>. This was an excellent session and proved to be beneficial.]]></description>
			<content:encoded><![CDATA[<p>Here at the <a href="http://www.mysqlconf.com" target="_blank">MySQL Conference and Expo</a>, Laura Thomson gave a great talk about Scalability and Performance Best Practices.</p>
<p>She had some interesting points about scalability. She basically said that no matter what language you write your web application, whether it&#8217;s compiled (C/C++) or interpreted (PHP, Java), you are subject to scalability issues. Another potential problem is optimizing before you know what exactly to optimize. This can lead to a loss of time that could have been spent on more important things.</p>
<p>Laura&#8217;s talk covers three types of best practices: general, scalability, and performance.</p>
<h4>General Best Practices</h4>
<p>First tip is to profile early and profile often. The earlier you can detect poor performance, the easier it is to fix. There are a handful of tools (<a href="http://pecl.php.net/package/apd" target="_blank">APD</a>, <a href="http://xdebug.org" target="_blank">Xdebug</a>, <a href="http://framework.zend.com" target="_blank">Zend</a>) that can help with profiling. Use system profiling tools such as <a href="http://sourceforge.net/projects/strace" target="_blank">strace</a>, <a href="http://www.sun.com/bigadmin/content/dtrace" target="_blank">dtrace</a>, and <a href="http://packages.debian.org/unstable/utils/ltrace.html" target="_blank">ltrace</a> to gather more information.</p>
<p>There are two types of effective profiling: debugging and habitual. Debugging profiling is about spotting deviations from the norm and habitual profiling is making the norm better. Profiling is an art and requires lots of practice to know where to look.</p>
<p>It is essential that the IT admins and the developers cooperate. This allows crisis&#8217; to be handled properly, especially in production environments were outages are time critical. Team members should report alert the developers of any abnormal behavior changes after a new code release is pushed. Before pushing new code, schedule a launch window and procedures for having developers fix problems and possibly falling back to a previous version. Avoid pushing releases on Fridays, otherwise key team members may be unavailable or over worked on the weekend.</p>
<p>It is recommended to test your application with production data. Test data may not take into account certain scenarios where bugs can be introduced. It is advised to have a staging environment which uses production data and also undergoes simulated load testing.</p>
<p>In order for you to track your application&#8217;s performance, you should record your applications performance over a period of time, then analyze the data to find potential issues. There are several means of tracking performance including access logs, system metrics, application profiling, and query profiling.</p>
<p>When a problem occurs, don&#8217;t make assumptions. The problem may be caused by something other than what you think it might be.</p>
<h4>Scalability Best Practices</h4>
<p>When the web application begins to suffer performance issues, start to decouple and isolate components to track down the source. If you need to tweak code, spend only enough time to refactor as needed. Reduce load on servers by moving static content on to dedicated servers.</p>
<p>By default, PHP stores session data on the hard drive. This can cause performance issues and can benefit from storing the session data in a database or better yet in a distributed cache such as <a href="http://www.danga.com/memcached" target="_blank">memcached</a>.</p>
<p>The most important thing you can do to improve performance is to cache as much data as possible. There are many levels of caching. You can cache data sets or precomputed fragments. For things like images, you can set up dedicated services for caching and serving static content. The usual suspects are recommended for caching (APC, memcached, <a href="http://www.squid-cache.org" target="_blank">Squid</a>).</p>
<p>PHP out of the box does not cache compiled pages. That means that ever request, each page has to be parsed and executed. Extensions such as APC and Zend can cache the compiled pages for an immediate speed improvement.</p>
<p>MySQL&#8217;s query cache works, but isn&#8217;t necessarily implemented the best way. If you query a table, the results are cached on the MySQL server. If a row is inserted, updated, or deleted, the entire cache is flushed. This supposedly has been fixed in MySQL 5.1, but a setting has to be set to not flush the cache.</p>
<p>To scale, your data can be federated across multiple MySQL servers. There can be complications with regards to data reliability and table joins can suffer from major speed hits.</p>
<p>A more reliable way to scale is to use replication. Replication does suffer from &#8220;slave lag&#8221; issues. The reason the lag can be high is because the master server uses multiple threads to store the data locally. The slave server has to process the replicated items in a single threaded mode to ensure the order of which the transactions is preserved. You can display the status of MySQL&#8217;s I/O and SQL thread by executing a <code>SHOW PROCESSLIST</code> statement.</p>
<p>The more database writes, the greater the lag. Depending on your application, you may only want to use replication for failover or backups.</p>
<p>Sometimes you may benefit from designing your application to avoid situations where data is hard to scale and can&#8217;t easily be cached.</p>
<h4>Performance Best Practices</h4>
<p>You definitely want to use a compiler cache. As described above, use APC or Zend for PHP5. If you are connecting to an external data source, perhaps a web service or data feed, minimize the number of instances you request them. Cache their response if possible. You may be able to load the data dynamically using Javascript and a little Ajax magic. Maybe the data isn&#8217;t a must have or maybe you can have a page dedicated to display the 3rd party data.</p>
<p>When tuning your applications performance, change one thing at a time. If you change more than one thing, how do you know which change caused the improvement and how do you know if you didn&#8217;t introduce new bugs changing the other things. Use MySQL&#8217;s EXPLAIN statement to profile your queries and enable the slow query logging. Use <a href="http://jeremy.zawodny.com/mysql/mytop" target="_blank">MyTop</a> or <a href="http://sourceforge.net/projects/innotop" target="_blank">InnoTop</a> to help profile your queries.</p>
<p>It is crucial that your database is properly indexed. If a table has poorly designed indexes or perhaps too many indexes. Use the smallest data type possible and try to design your tables to be fixed width. That means, use char instead of varchar, set the length of your fields to logical lengths (ie use 128 chars instead of 107 chars). De-normalize when necessary. Remove static data out of the database or store it in a MEMORY table. Use the appropriate storage engine for each table.</p>
<p>For your queries, minimize the number of queries and cache them outside the database when possible.</p>
<p>She claims that deeply recursive code is expensive in PHP. Make sure you are not doing unnecessary looping. If you find that you are, chances are you are doing something wrong and that there is a better idiom for performing the task.</p>
<p>Don&#8217;t try to work around or re-write perceived inefficiencies in PHP. Use regular expressions to do intense string manipulation. instead of writing complex serialization code, use PHP&#8217;s extensions to do the heavy lifting. Before spending time to write some boilerplate function, check to see if there are any extensions that exist that could help save you time.</p>
<p>Laura gave this talk on behalf of George Schlossnagle. George&#8217;s original presentation can be found at <a href="http://omniti.com/~george/talks" target="_blank">http://omniti.com/~george/talks</a>. This was an excellent session and proved to be beneficial.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cb1inc.com/2007/04/24/scalability-and-performance-best-practices/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>We Are Clear for Take Off!</title>
		<link>http://www.cb1inc.com/2007/04/09/we-are-clear-for-take-off/</link>
		<comments>http://www.cb1inc.com/2007/04/09/we-are-clear-for-take-off/#comments</comments>
		<pubDate>Mon, 09 Apr 2007 17:16:57 +0000</pubDate>
		<dc:creator>Chris Barber</dc:creator>
				<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Today marks the launch of the new CB1, INC. website! In addition to a blog, we've organized the projects section and will continue to add new content.

This blog will be very technical, so you won't be hearing about boring non-technical stuff, just the boring technical stuff.

As you may already know, CB1, INC. is a technology consulting company. Custom software development and website design for enterprises is our primary business. Feel free to <a href="http://cb1inc.com/contact">contact us</a> if you have questions or you think CB1 can be of service to you!]]></description>
			<content:encoded><![CDATA[<p>Today marks the launch of the new CB1, INC. website! In addition to a blog, we&#8217;ve organized the projects section and will continue to add new content.</p>
<p>This blog will be very technical, so you won&#8217;t be hearing about boring non-technical stuff, just the boring technical stuff.</p>
<p>As you may already know, CB1, INC. is a technology consulting company. Custom software development and website design for enterprises is our primary business. Feel free to <a href="/contact/">contact us</a> if you have questions or you think CB1 can be of service to you!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cb1inc.com/2007/04/09/we-are-clear-for-take-off/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

