<?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>select * &#187; Monday School</title>
	<atom:link href="http://aptoma.com/select.star/category/monday-school/feed/" rel="self" type="application/rss+xml" />
	<link>http://aptoma.com/select.star</link>
	<description>web-development, and other issues we really, really care about</description>
	<lastBuildDate>Thu, 22 Apr 2010 19:53:48 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Limit Work to Capacity</title>
		<link>http://aptoma.com/select.star/2010/04/22/limit-work-to-capacity/</link>
		<comments>http://aptoma.com/select.star/2010/04/22/limit-work-to-capacity/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 19:50:18 +0000</pubDate>
		<dc:creator>Geir Berset</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[teamwork]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=1233</guid>
		<description><![CDATA[Hard work does not pay off. At least not if your ultimate goal is to improve at what you do. And not if what you do is quality product development.
In that case you need to build in slack for learning into the system. You want everyone to have time for sharing, improving and learning continuously, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://cheese-burger.net/"><img class="alignright size-medium wp-image-1248" title="Picture 1" src="http://aptoma.com/select.star/wp-content/uploads/2010/04/Picture-1-300x179.png" alt="" width="300" height="179" /></a><a href="http://olvemaudal.wordpress.com/2010/02/12/hard-work-does-not-pay-off/">Hard work does not pay off</a>. At least not if your ultimate goal is to improve at what you do. And not if what you do is quality product development.</p>
<p>In that case you need to build in slack for learning into the system. You want everyone to have time for sharing, improving and learning continuously, and you want to be able to come home from work with energy to pursue your goals for personal skill development even further.</p>
<p>It&#8217;s great fun to be good at what you choose to spend your life doing.</p>
<p>Since the primary raw materials in software product development are skills and intellect, rapid learning is the prime goal and the capital for product development. Fail to invest in raw materials for your business, and you&#8217;ll soon run out of stock. Don&#8217;t <em>allow</em> for time to learn, rather, <em>require</em> it.</p>
<h3>Running a system at 100% yields all sorts of problems.</h3>
<p>Symptoms include</p>
<ul>
<li>You stop talking to each other. &#8220;Sorry, can&#8217;t help, have to go do this thing that is  really urgent&#8221;</li>
<li>You start building technical debt. &#8220;If I just skip to write that test (it&#8217;s really hard to write), then I can save 2 hours today to get to the next thing I have to do.&#8221;</li>
<li>Shallow bug-fixing. &#8220;Need to fix this bug real fast, in order to get the other 4 bugs done, too! No time for digging further&#8221; Root cause analysis and regression testing get skimped on.</li>
<li>Useful, although sometimes inconclusive and somewhat directionless, discussions plainly stops happening.</li>
<li>Stress activates your lizard brain, which numbs the rational being. You are in survival mode.</li>
<li>Work gets less inspiring and fun, which slows things down. Inspiration is high-octane fuel.</li>
<li>People get exhausted, and energy-level is low during, and after work hours. You need to &#8220;relax&#8221; on Facebook at work and in front of the TV at home, instead of doing inspirational learning.</li>
</ul>
<p><a href="http://aptoma.com/select.star/wp-content/uploads/2010/04/congestion.jpg"><img class="alignnone size-full wp-image-1243" title="congestion" src="http://aptoma.com/select.star/wp-content/uploads/2010/04/congestion.jpg" alt="" width="550" height="306" /></a></p>
<p style="text-align: right;"><span style="color: #808080;">(Picture from </span><a href="http://en.wikipedia.org/wiki/File:Moscow_traffic_congestion.JPG"><span style="color: #808080;">Wikimedia commons</span></a><span style="color: #808080;">)</span></p>
<p>If you have trouble grasping the concept, picture a congested highway. If you remove a small percentage of the cars, you get a magnitude of improvement in throughput and speed. <a href="http://en.wikipedia.org/wiki/Traffic_congestion">This is a fact</a>.</p>
<p>Did you ever try to squeeze a washing machine 100% full? No clothes get cleaned. Remove 10 or 20% of the clothes, and you have a winner.</p>
<h3><strong>Don&#8217;t maximize utilization.<br />
Build in time for learning, improving and sharing.</strong></h3>
<p>If you, as we have been, find yourself in this mess. There are several ways to get out of it.</p>
<ol>
<li><strong>Say no.</strong> If you never say no, you don&#8217;t have a strategy &#8212; say no to the least important stuff. Saying no is hard, scary and extremely useful.</li>
<li><strong>If you work for a consultancy firm, give up</strong>. Incentives for maximizing utilization is too high in consultancy companies, as they get paid for &#8220;productive hours&#8221; only. Quit your job, and go to work in a product development company, or a skilled in-house team. Anything but most consultancy firms, they will cannibalize you.</li>
<li><strong>Scale up capacity to meet demand</strong>. What can I say, <a href="http://aptoma.com/career">we are hiring</a>.</li>
</ol>
<h3><strong>Quantified</strong></h3>
<p>This is no science, but if I would be forced to put some numbers on this, I&#8217;d say that:</p>
<ul>
<li>Build in approximately 20% learning/sharing time during normal work hours. Yes, that&#8217;s one whole day a week. We use it for our <a href="http://aptoma.com/select.star/category/monday-school/">monday school</a>, impulsive discussions, reading, friday meeting (our arena for general discussions on processes) and blogging, to mention some activities.</li>
<li> If you want, you can probably &#8220;work&#8221; 60 hours a week or more without any danger of burning out, but <em>only as long as</em> that time is spent balanced and having fun, learning and improving/being productive &#8212; and only if personal situation allows for it without sacrificing time spent on other important values, like your kids.</li>
<li>Don&#8217;t build overtime into your standard operating procedures. Required overtime doing &#8220;productive&#8221; work should be the rare exception, not the default.</li>
</ul>
<p>Find a sustainable pace where you are balancing learning, improving, being productive and all of the time having fun. That&#8217;s an important ingredient in the recipe for success.</p>
<p>By the way, did I mention that <a href="http://aptoma.com/career">we&#8217;re hiring</a> or that <a href="http://aptoma.com/career">we&#8217;re hiring</a>?</p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2010/04/22/limit-work-to-capacity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automated Unit Testing for JavaScript</title>
		<link>http://aptoma.com/select.star/2010/03/03/automated-unit-testing-for-javascript/</link>
		<comments>http://aptoma.com/select.star/2010/03/03/automated-unit-testing-for-javascript/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 15:53:25 +0000</pubDate>
		<dc:creator>Patrik Henningsson</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=1192</guid>
		<description><![CDATA[In our work towards Continuous Deployment and an improved approach to JavaScript we are missing one very important thing &#8211; automated unit testing for JavaScript. Currently we have have some tests written in TestCase that will run in the browser. But we need away to automate this without the need of a browser so we have [...]]]></description>
			<content:encoded><![CDATA[<p>In our work towards <a href="http://aptoma.com/select.star/2010/01/21/notes-on-continuous-deployment/">Continuous Deployment</a> and an <a href="http://aptoma.com/select.star/2010/02/01/enterprise-javascript-coding/">improved approach to JavaScript</a> we are missing one very important thing &#8211; automated unit testing for JavaScript. Currently we have have some tests written in <a href="http://rubyforge.org/projects/testcase/">TestCase</a> that will run in the browser. But we need away to automate this without the need of a browser so we have started to look at some alternatives.</p>
<p><strong>The solution we&#8217;re currently playing around with is <a href="http://www.mozilla.org/rhino/">Rhino</a> + <a href="http://www.envjs.com/">Env.js</a> + <a href="http://docs.jquery.com/QUnit">QUnit</a>.</strong></p>
<p>Rhino is a JavaScript implementation written in Java and you can run it in a terminal, which harmonize with our aim for automation.</p>
<p>Env.js is a DOM implementation written entirely in JavaScript and will simulate the basic functions of a browser.</p>
<p>QUnit is simply the framework for the unit tests.</p>
<p>So far it looks very promising and it looks like we can do much of our testing in this environment. We will post more of our discoveries here later when we have done more testing, so <a href="http://feeds.feedburner.com/aptoma/selectstar">stay tuned</a> or follow me on twitter (<a href="http://twitter.com/pahen">@pahen</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2010/03/03/automated-unit-testing-for-javascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A first look at JavaScript Frameworks</title>
		<link>http://aptoma.com/select.star/2010/02/22/a-first-look-at-javascript-frameworks/</link>
		<comments>http://aptoma.com/select.star/2010/02/22/a-first-look-at-javascript-frameworks/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 12:31:45 +0000</pubDate>
		<dc:creator>Michael Plikk</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=1175</guid>
		<description><![CDATA[In our discussion today about Javascript frameworks we finally came to a conclusion, of sort, regarding when to use frameworks. 
In back office applications we can use whatever framework we want. It is used by a small number of people and we have total control over possible dependencies and namespace collisions, so we do not [...]]]></description>
			<content:encoded><![CDATA[<p>In our discussion today about Javascript frameworks we finally came to a conclusion, of sort, regarding when to use frameworks. </p>
<p>In back office applications we can use whatever framework we want. It is used by a small number of people and we have total control over possible dependencies and namespace collisions, so we do not have to worry about breaking other people&#8217;s stuff. </p>
<p>When we create code that is going to be included on another web page it is a completely different story. In those cases our goal will be to create code that does not require a framework, so we avoid polluting the requiring site with our dependencies. It might not always be possible to achieve this, but it is a noble goal at least.</p>
<p>We have been using <a href="http://prototypejs.org/" alt="Prototype JavaScript framework: Easy Ajax and DOM manipulation for dynamic web applications">Prototype</a> for most of our work so far. On smaller projects we have started to dabble a bit in <a href="http://jquery.com/" alt="JQuery: The Write Less, Do More, JavaScript Library">JQuery</a> and <a href="http://developer.yahoo.com/yui/index.html" alt="YUI Library">YUI</a>. The next time we do any major JavaScript development we will explore the options they give us. </p>
<p>The major reasons for moving away from Prototype is the huge size of the library, and numerous changes it makes to basic JavaScript objects. A lot of the changes are good and make for easier code development, but they don&#8217;t really feel like proper JavaScript. Instead they rely too much on magical functions and the forced object oriented coding style that Prototype enforces.</p>
<p>We also find that Prototype (and Scriptaculous) are lacking in regards to their option for &#8220;plugins&#8221;, like calendar- or graph-plugins. Either Scriptaculous have a solution built in, or there are very few good alternatives. Both JQuery and YUI seem to have better communities surrounding them that develop better, and more, plugins that might suit our needs.</p>
<p>The little experience we have with JQuery so far indicates that it is very DOM-centred. This is both a boon and a bane; we loose some of the power we might have gotten used to in Prototype, but it might help us creating purer JavaScript for code in the areas that do not touch on the DOM. This is a goal we have since we want to make all of our JavaScript code testable, and it is much easier to test code that only manipulate data and do not touch the DOM.</p>
<p>Another option in regards to plugins that we are going to look into is <a href="http://www.extjs.com/" alt="Ext JS — JavaScript Framework and RIA Platform">ExtJS</a>. The GUI elements that they offer seem to be very powerful, and using pre-built items would save us a lot of time. The pitfall that we saw was that overuse of the items they supply might make the application look too much like a desktop application. Since we are developing for the web we should be careful to not draw too much inspiration from the desktop, they are different media and require different solutions.</p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2010/02/22/a-first-look-at-javascript-frameworks/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>JavaScript: Tools, Coding Standard and Guidelines</title>
		<link>http://aptoma.com/select.star/2010/02/08/javascript-tools-coding-standard-and-guidelines/</link>
		<comments>http://aptoma.com/select.star/2010/02/08/javascript-tools-coding-standard-and-guidelines/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 13:54:33 +0000</pubDate>
		<dc:creator>Geir Berset</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[checklist]]></category>
		<category><![CDATA[guideline]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[standard]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=1123</guid>
		<description><![CDATA[We&#8217;re currently devoting an hour each Monday to collectively work our way through JavaScript. Our aim is to point to the key areas of interest and improvement, and to dig into each area one by one.
We are maintaining a TOC for our JS-discussions here.
Development Tools

Firebug is the most important development tool for us, without comparison. [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re currently devoting an hour each Monday to collectively work our way through JavaScript. Our aim is to point to the key areas of interest and improvement, and to dig into each area one by one.</p>
<p>We are maintaining a <a href="http://aptoma.com/select.star/2010/02/01/enterprise-javascript-coding/">TOC for our JS-discussions here</a>.</p>
<h3>Development Tools</h3>
<p><a href="http://getfirebug.com"><img class="alignnone size-full wp-image-1124" title="Picture 1" src="http://aptoma.com/select.star/wp-content/uploads/2010/02/Picture-1.png" alt="" width="411" height="111" /></a><a href="http://getfirebug.com/"></a></p>
<p><strong><a href="http://getfirebug.com/">Firebug</a> is the most important development tool for us</strong>, without comparison. Everyone is familiar with this time-tested tool.</p>
<p>You will rarely need more than Firebug, although there are some valid alternatives now, in 2010. Chrome, Safari and Opera (Dragonfly) have all internal tools for debugging (and more). None of us have used those tools extensively, so we don&#8217;t know more than what we have heard from third parties, which is mostly positive. If you need to spot errors in IE, <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=2F465BE0-94FD-4569-B3C4-DFFDF19CCD99&amp;displaylang=en">Microsoft Script Debugger</a> is your best hope. IE8 ships with this integrated as default. No-one in our team reported ever making use of the Firebug Light for IE.</p>
<p><strong>When it comes to JavaScript editors</strong>, we find that no text editor seems to differ significantly from the rest. Most editors provide color-formatting, some provide API-reference with autocompletion and some editors like vim and TextMate can be configured for auto-validation through JSLint.</p>
<h3>Coding Standard</h3>
<p>Our coding standard for JavaScript builds on our own internal PHP Coding standard as far as it fits, which in turn builds on the publicly available <a href="http://framework.zend.com/manual/en/coding-standard.coding-style.html">Zend Framework Coding standard</a>.</p>
<p><strong>We have boiled our standard down to this shortlist.</strong></p>
<ul>
<li>Follow <a href="http://framework.zend.com/manual/en/coding-standard.coding-style.html">the Zend  Framework Coding standard</a></li>
<li>Use an underscore in front of private objects. (i.e. var _private = 0;) Private objects and methods can be defined as «trusted» with everything else foreign and error-prone. This can make your core more stable and rigid without having to overdo it with data-testing and integrity validation.</li>
</ul>
<p>It is possible to achieve a private scope in JavaScript, but it comes at a cost in complexity, and we have decided against it. Our decision is based on experience and advice given in &#8220;<a href="http://www.dustindiaz.com/pro-javascript-design-patterns/">Pro Javascript Design Patterns</a>&#8220;.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * Rationale and short description of ClassName.
 */</span>
<span style="color: #003366; font-weight: bold;">var</span> objectName <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    myFunction<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>whatToDo<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> whatToDo <span style="color: #339933;">===</span> <span style="color: #3366CC;">'string'</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> whatTodo.<span style="color: #660066;">length</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            objectName._doWhatYouGottaDo<span style="color: #009900;">&#40;</span>whatToDo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    _doWhatYouGottaDo<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>whatToDo<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #006600; font-style: italic;">// As this is a private function, I trust the type and data validity of the argument</span>
      <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>whatToDo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The above is a minimal example, which in no way covers all the rules accurately.</p>
<h3>Guidelines<strong> </strong></h3>
<p><strong>Global scope. </strong>Put as little garbage as possible in the global scope. Use well-named objects as namespaces and if needed sub-namespaces. Know the results of using or skipping &#8220;var&#8221; when creating objects.</p>
<p><strong>Use closures,</strong> with care! Closures are necessary in JavaScript, but as not all languages have them, they will to an inexperienced JS-programmer look too much like Magic(TM), which isn&#8217;t too good. Use good judgement when to use them, and  remember good inline commenting to make the magic more transparent.</p>
<p><strong>Don&#8217;t use the &#8220;new&#8221; operator</strong>. When setting up prototype inheritance it has to be used, but there are no other cases where it should be used. In most cases it&#8217;s not only slow, but the alternatives are often easier to understand, require less code and are more powerfull. Because of this, we have decided to conform on code without <em>new</em>. As examples, new Array and new Object should be written as [] and {}.<strong> </strong></p>
<p><strong>Prototype inheritance</strong> contains power for object oriented code. We will return with more  guidelines when our experience grow. We must admit not to have used this elaborately. A serious liability of PrototypeJS (the framework we use<strong>d</strong>) is that it overrides prototype (the language feature) from JavaScript.</p>
<p><strong>Few anonymous functions.</strong> As a rule of thumb, we say: <em>name functions</em>. This has to do with testability and readability of your code. The exception is if you need a  &#8220;one-liner&#8221; to use just once, in which case anonymous functions are OK. You would normally not test these kind of functions.</p>
<p><strong>Lint your code! </strong>Lint is a code quality tool, and it will hurt your feelings. But  that pain is just Douglas Crockford stabbing the parts of you responsible for writing bad JavaScript. You end up stronger in the end.</p>
<h3>Recommended research material</h3>
<p>JavaScript requires effort on your behalf. You need to do the homework if you want to be a powerful and successful JavaScript developer. For starters we recommend these resources:</p>
<ul>
<li>Closures : <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Closures">Working with closures</a> and <a href="http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/">Explaining JavaScript scope and closures.</a></li>
<li><a href="http://video.yahoo.com/watch/630959/2974197">Douglas Crockford: &#8220;JavaScript &#8211; The Good Parts&#8221; (video)</a></li>
<li><a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">Douglas Crockford: &#8220;JavaScript &#8211; The Good Parts&#8221; (amazon)</a><a href="http://ajaxian.com/archives/javascript-the-good-parts"><br />
</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2010/02/08/javascript-tools-coding-standard-and-guidelines/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Enterprise JavaScript Coding</title>
		<link>http://aptoma.com/select.star/2010/02/01/enterprise-javascript-coding/</link>
		<comments>http://aptoma.com/select.star/2010/02/01/enterprise-javascript-coding/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 14:55:17 +0000</pubDate>
		<dc:creator>Geir Berset</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=1097</guid>
		<description><![CDATA[Not many years ago, people would giggle and think of enterprise and JavaScript as an oxymoron. Not so much anymore. If you want to be a serious actor even in (or maybe especially in) the enterprise software market, you have to take JavaScript seriously. Large parts of your product&#8217;s business logic might find its way [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://aptoma.com/select.star/wp-content/uploads/2010/02/18okt04_ajax_logo_150_rgb.jpg"><img class="alignright size-medium wp-image-1109" style="border: 0px;" title="18okt04_ajax_logo_150_rgb" src="http://aptoma.com/select.star/wp-content/uploads/2010/02/18okt04_ajax_logo_150_rgb-284x300.jpg" alt="" width="284" height="300" /></a>Not many years ago, people would giggle and think of enterprise and JavaScript as an oxymoron. Not so much anymore. If you want to be a serious actor even in (or maybe especially in) the enterprise software market, you have to take JavaScript seriously. Large parts of your product&#8217;s business logic might find its way into your JavaScript scope, not to mention your GUI elements, and you must be prepared when it does.</p>
<p>We have decided to address JavaScript with more care. We&#8217;d like to give it the time and focus it deserves. Not to be mistaken, we are probably in the top 5% of businesses going deep into JavaScript on our enterprise software, but we still feel we can go further &#8212; especially in the fields of quality assurance and scaling.</p>
<p>Lo and behold, we give you;</p>
<h3><strong>Monday School Notes from JavaScript session #1</strong></h3>
<h4>Table of Content</h4>
<p>We have decided to divide the subject of JavaScript into the following sections:</p>
<ul>
<li><a href="http://aptoma.com/select.star/2010/02/08/javascript-tools-coding-standard-and-guidelines/">Development Tools</a></li>
<li><a href="http://aptoma.com/select.star/2010/02/08/javascript-tools-coding-standard-and-guidelines/">Coding standard</a></li>
<li><a href="http://aptoma.com/select.star/2010/02/08/javascript-tools-coding-standard-and-guidelines/">Guidelines</a></li>
<li><a href="http://aptoma.com/select.star/2010/02/22/a-first-look-at-javascript-frameworks/">Frameworks, or the lack thereof</a> (when to use what)</li>
<li>Testing</li>
<li>Debugging</li>
<li>Patterns</li>
<li>Document Object Model (DOM)</li>
<li>Productivity tips</li>
<li>Compatibility issues</li>
<li>Recommended reading/watching</li>
</ul>
<p>We&#8217;ll be covering these topics in the weeks to come, and we well be returning with links on the TOC. If you will join us in this, please follow <a href="http://feeds.feedburner.com/aptoma/selectstar">this blog on RSS</a> or follow <a href="http://twitter.com/aptoma">the company</a> or <a href="http://twitter.com/geirber">the author</a> on twitter. If you digg  it, then <a href="http://digg.com/programming/Notes_on_Continuous_Deployment">digg  it</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2010/02/01/enterprise-javascript-coding/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Caching Concluded (for now)</title>
		<link>http://aptoma.com/select.star/2009/11/16/caching-concluded-for-now/</link>
		<comments>http://aptoma.com/select.star/2009/11/16/caching-concluded-for-now/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 13:39:42 +0000</pubDate>
		<dc:creator>Geir Berset</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=865</guid>
		<description><![CDATA[It&#8217;s been very interesting looking at different technologies and strategies, and we are now concluded and will be leaving the topic of caching for now.
Caching Todo-items
Reverse Proxy Caching and ESI
We will be creating an internal guideline-document for using Varnish, which we&#8217;ll also publish here on the blog. Varnish is a simple, fast and stable technology [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-877" title="hammertime" src="http://aptoma.com/select.star/wp-content/uploads/2009/11/hammertime.jpg" alt="hammertime" width="290" height="246" />It&#8217;s been very interesting looking at <a href="http://aptoma.com/select.star/2009/11/05/7-approved-caching-technologies/">different technologies</a> and <a href="http://aptoma.com/select.star/2009/10/22/caching-strategies/">strategies</a>, and we are now concluded and will be leaving the topic of caching for now.</p>
<h3>Caching Todo-items</h3>
<p><strong>Reverse Proxy Caching and ESI<br />
</strong>We will be creating an internal guideline-document for using Varnish, which we&#8217;ll also publish here on the blog. Varnish is a simple, fast and stable technology excellently suited for the job (Reverse Proxy Caching and Edge Side Includes).</p>
<p><strong>Data Caching<br />
</strong>We will be re-implementing our data-cache layer in our framework, namely AFWCache. The goal is keep options open for future technologies, while solving today&#8217;s needs elegantly (as in: sustainable software development). It will become an abstract class which through use of the <a href="http://en.wikipedia.org/wiki/Adapter_pattern">adapter pattern</a> will support our two technologies of choice, namely Memcache and APC, which serves as both opcode cache and data cache layer.</p>
<h3>Future topics for Aptoma Monday School</h3>
<p>We&#8217;ll be spending this week considering a new set of challenges to thrive on. We&#8217;ll conclude this Friday in which direction we&#8217;ll move.</p>
<ul>
<li>JavaScript Guidelines</li>
<li>Upgraded database adapter class for our framework</li>
</ul>
<p>Suggestions? <a href="http://feeds.feedburner.com/aptoma/selectstar">Hang in there (RSS)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2009/11/16/caching-concluded-for-now/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>7 Approved Caching Technologies</title>
		<link>http://aptoma.com/select.star/2009/11/05/7-approved-caching-technologies/</link>
		<comments>http://aptoma.com/select.star/2009/11/05/7-approved-caching-technologies/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 23:23:04 +0000</pubDate>
		<dc:creator>Geir Berset</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[checklist]]></category>
		<category><![CDATA[improvement]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=838</guid>
		<description><![CDATA[(These are the notes from Aptoma Monday School for week #44 and #45)
We have recently been blogging our notes on different modi operandi of caching. To sum it up, these were: reverse proxy caching, application caching (view caching, subview caching and object/data-caching), opcode caching, client caching and query caching.

We have spent the last two weeks [...]]]></description>
			<content:encoded><![CDATA[<p>(These are the notes from Aptoma Monday School for week #44 and #45)</p>
<p>We have recently been blogging our notes on <a href="http://aptoma.com/select.star/2009/10/22/caching-strategies/">different modi operandi</a> of caching. To sum it up, these were: reverse proxy caching, application caching (view caching, subview caching and object/data-caching), opcode caching, client caching and query caching.</p>
<p><img class="alignnone size-full wp-image-850" title="what-are-you-looking-at" src="http://aptoma.com/select.star/wp-content/uploads/2009/11/what-are-you-looking-at.jpg" alt="what-are-you-looking-at" width="560" height="196" /></p>
<p>We have spent the last two weeks discussing which technologies fits our needs best. Our product installations handle high traffic (i.e. millions of views a day) and we also have products that produce a lot of data that is heavy to compute (i.e. large data sets computed from complex database queries). Thus we have to scale both vertically and horizontally, so to speak. Our needs of caching is thus quite broad, and we have to shop for a lot of technologies in order to fulfill all our needs. This brings us to our &#8230;</p>
<h3>List of  7 Approved Caching Technologies</h3>
<p>In this post we will provide a few notes on each technology.</p>
<p><strong>1. Varnish.</strong><br />
Used for reverse proxy caching. We are not happy with hosting providers ability to configure and fine tune Varnish, so rehearsing your skills in this is certainly not a waste of time.</p>
<p><strong>2. APC Opcode Cache</strong>.<br />
Use it. Always. We cannot find examples for when not to. It will speed  up execution with no known disadvantages. APC seems to perform better  than both competing alternatives (xcache and zend accellerator) under all circumstances.</p>
<p><strong>3. APC for data caching</strong>.<br />
You can use APC for data caching, as well. It will outperform  memcache  by a factor of 10 to 50(!). As opposed to memcache, it does not have distributed access. We have no idea what happens when you exhaust   the assigned RAM for data caching. We will have to find out, won&#8217;t we?  <span style="color: #ffffff;">(Yes we  will)</span></p>
<p><strong>4. Memcache for data caching</strong>.<br />
Memcache is still one of the most stable and high performing  technologies for its use. It is nevertheless annoying that its  performance is significantly slowed down by the fact that it runs on top  of TCP/IP (which is also an advantage when it comes to flexibility),  even in those cases where only local access is necessary. It seems to us  that memcache is run on the same server as the application in more than  90% of all cases.</p>
<p><strong>5. Varnish ESI.</strong><br />
As the name implies, this is a feature of Varnish. ESI is very interesting as it implements subview caching without having to implement it at application level (slower). Implementing subview caching on reverse proxy level can speed things up significantly given the right circumstances. A disadvantage of Varnish ESI is that it introduces more complexity to your source code, as you&#8217;ll have to write &#8220;Varnish markup&#8221; in order to have Varnish do edge side includes for you (<tt>&lt;esi:include&gt;)</tt>. Not a big deal, but definitively a declared enemy of the simplicity ninja. The benefits might make it worthwhile, nevertheless.</p>
<p><strong>6. MySQL for data caching</strong>.<br />
This is basically &#8220;use MySQL the way you would do memcache&#8221;. MySQL for data caching performs quite well, but not really astonishing (memcache is about twice as fast in our tests). MySQL is a convenient technology, as we already require it on all our products, it is also one of the more available technologies regardless of hosting partner (and we have quite a few of them). Another advantage of using database technologies for this purpose is that more sophisticated queries can be applied for purging and invalidating data, than can you in the simpler (but faster) key value databases (memcache et.al).</p>
<p><strong>7. SQLite for data caching</strong>.<br />
Same use case as with MySQL above, and with the same pros and cons. It does perform a little better than MySQL. We have decided to look more into this one. Another advantage over memcache is that SQLite and MySQL become persistent caches, (whereas memcache is volatile, i.e. will be blank after a restart).</p>
<h3>List of Discarded Technologies</h3>
<p>APC as data cache and Varnish ESI are the only technologies which we have not exhaustively used in production for years. Nevertheless we will seek to improve our way of using all these technologies in the time to come, and we will be looking for how to implement support for these in our framework (Aptoma Framework, AFW). To show that we did not just stick to our guns on this one, we present this short list of alternative technologies which we also explored during our tests.</p>
<ul>
<li>Tokyo Tyrant (reason to discard : somewhere in between MySQL and Memcache in performance, and brings no new advantages to the blend)</li>
<li>Nginx (not really a caching technology, merely a faster web-server in special circumstances)</li>
<li>Lighttpd (Not a caching technology, but can provide faster delivery of static content than Apache can deliver. On dynamic content it does not perform better than a properly stripped and fine tuned Apache.)</li>
<li>DBA (Does not perform as well as APC in our tests).</li>
</ul>
<h3><strong>We have more discussions to come!</strong></h3>
<p>On our wish-list (todo-list) for caching and performance discussions is as follows.</p>
<p><strong>Better benchmarking<br />
</strong></p>
<ul>
<li> Siege</li>
<li>Jmeter</li>
<li>Apache Benchmark (ab)</li>
<li> Httperf</li>
</ul>
<p><strong>Caching techniques</strong></p>
<ol>
<li> Pre-loading  cache (warming)</li>
<li> Event triggered cache invalidation (cache on update)</li>
<li>Stale cache (set flag but don&#8217;t purge, combined with a grace time in reverse proxy)</li>
<li> Better caching on logged in users (Varnish ESI use case)</li>
<li> Setting proper headers (for improved client caching<span> and more)<br />
</span></li>
</ol>
<h3>Notes From some of our Benchmark Tests</h3>
<h4><strong>Tokyo Tyrant</strong></h4>
<p>Tokyo Tyrant is a memcache-like layer on top of Toky0 Cabinet, which is a fast key-value database. (see : <a href="http://sameerparwani.com/posts/tokyo-cabinet-and-tokyo-tyrant" target="_blank">http://sameerparwani.com/posts/tokyo-cabinet-and-tokyo-tyrant</a>) Installation was easy, everything required was available at <a href="http://1978th.net/" target="_blank">http://1978th.net/</a>. As a  PHP-wrapper we used <a href="http://mamasam.indefero.net/p/tyrant/downloads/2/" target="_blank">http://mamasam.indefero.net/p/tyrant/downloads/2/</a></p>
<p>We tested Tokyo  Tyrant with default settings (defaults matter). The same goes for the comparisons, Memcache and MySQL  (query cache is off). The time given bellow is the time it took to set and get 1000 variables off 1 kB.</p>
<p><em>TokyoTyrant </em></p>
<ol>
<li>put: 0.102526473999</li>
<li>get: 0.121464586258</li>
</ol>
<p><em>TokyoTyrant  disk hash </em></p>
<ol>
<li>put: 0.108086037636</li>
<li>get: 0.123809480667</li>
</ol>
<p><em>TokyoTyrant  disk B-Tree </em></p>
<ol>
<li>put: 0.111338186264</li>
<li>get: 0.129682970047</li>
</ol>
<p><em>Memcache</em></p>
<ol>
<li>put: 0.0864425897598</li>
<li>get: 0.0702331066132</li>
</ol>
<p><em>MySQL  without Query Cache </em></p>
<ol>
<li>put: 0.112287640572</li>
<li>get:  0.164221072197</li>
</ol>
<p>Tokyo Tyrant is slower than  Memcache. Tokyo Cabinet  can probably outperform memcached if accessed directly, but no PHP-bindings for this purpose were available for our tests.</p>
<p>What is exciting is that Tokyo Tyrant is faster than  MySQL for persistent data caching. Tokyo Tyrant is also supposed to have some other features which we have currently did not have time to test. Please share any experiences you might have with Tokyo Tyrant.<span> </span></p>
<h4>MySql, SQLite, DBA, Memcached and APC tests</h4>
<p>The test : Write, then read and add to an array 100 000 MD5-hashes. For the relational databases, the insert is done with a multi-row-insert or a  transaction.</p>
<p><em>MySQL</em></p>
<ul>
<li>Create : 2038.615942 ms</li>
<li>Read : 13782.1378708 ms</li>
</ul>
<p><em>SQLite</em></p>
<ul>
<li>Create : 2084.01703835 ms</li>
<li>Read : 4064.75901604 ms</li>
</ul>
<p><em>DBA</em> (NOTE! Only with 10 000 elements this time)</p>
<ul>
<li>Create : 10192.3089027</li>
<li>Read : 10065.6449795</li>
</ul>
<p><em>Memcached</em></p>
<ul>
<li>Create : 3493.89410019</li>
<li>Read : 3219.08593178</li>
</ul>
<p><em>APC</em></p>
<ul>
<li>Create : 25127.6450157 ms</li>
<li>Read : 172.363996506 ms</li>
</ul>
<p>MySQL will insert a lot of rows at the same speed as SQLite. W/O query cache, it will be outperformed by a factor of three by SQLite.</p>
<p>SQLite supports :memory: instead of files, which can speed it up as a relational cache, but it is no longer persistent between restarts. MySQLs MEMORY-engine is more of the same.</p>
<p>DBA is a copy-on-write which means that every write will increase its file-size. This makes all operations slower the more writes you have to do. Performance loss was at times huge, but it can be fixed by issuing an optimize-command. DBA writes slowly, (50x slower than the relational databases, and much slower than the other hash-buckets). Reading from a clean file will make it perform somewhere in between the hash-buckets (memcache, APC) and the relational databases</p>
<p>Memcached is a little slower to write to than the relational databases, due to the databases doing all writes in a single command. Read is about the same as with SQLite and only twice as fast as MySql. (Bear in mind that this is a best case scenario for the relational databases)</p>
<p>APC is 5-10x slower than Memcached in writes, but 10-20x faster to read from in this test.</p>
<h4><strong>Test conclusions </strong></h4>
<p>DBA has few advantages over the relational databases. APC can replace Memcache in some of the areas in which we use memcache today (data/object-caching).</p>
<p><span><br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2009/11/05/7-approved-caching-technologies/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Caching Strategies (AMS week #43)</title>
		<link>http://aptoma.com/select.star/2009/10/22/caching-strategies/</link>
		<comments>http://aptoma.com/select.star/2009/10/22/caching-strategies/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 14:00:43 +0000</pubDate>
		<dc:creator>Geir Berset</dc:creator>
				<category><![CDATA[Monday School]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=788</guid>
		<description><![CDATA[This is the second post of our lecture notes from Aptoma Monday School &#8211; series (AMS). As it is lecture notes, you should expect the texsts to be a bit rough around the edges. We&#8217;ve decided to discuss and revise our caching strategies. Our session this week was spent settling upon a set of cache [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second post of our lecture notes from <a href="http://aptoma.com/select.star/category/monday-school/">Aptoma Monday School</a> &#8211; series (AMS). As it is lecture notes, you should expect the texsts to be a bit rough around the edges. We&#8217;ve decided to discuss and revise our caching strategies. Our session this week was spent settling upon a set of cache layers.</p>
<p><img class="alignnone size-full wp-image-803" title="disk-cache" src="http://aptoma.com/select.star/wp-content/uploads/2009/10/disk-cache.jpg" alt="disk-cache" width="560" height="176" /></p>
<p>To make things perfectly clear : <em>a cache is a temporary storage area where frequently accessed data can be stored for rapid access</em>.</p>
<h3>1. <span style="text-decoration: line-through;">Page caching</span> Reverse proxy caching<span style="text-decoration: line-through;"><br />
</span></h3>
<p>Caching the entire page is typically done using Varnish (see the technology references at the end of this article). Our experience with Varnish is that it is stable, and very high performance. However, people who really know how to configure it properly does not come by the dozen. As much as we could hope that all our hosting providers see it as their job to get to know this kind of blazing technology intimately, we can not rely on it, and thus we will have to leverage our own competency further in this area. A weak point of page caching through Varnish, is that once you set a client cookie, Varnish is forced to send traffic straight through (i.e. no caching whatsoever) or dispose of the cookie all together (i.e. <a href="http://varnish.projects.linpro.no/wiki/VCLExampleCacheCookies">break application functionality</a>). Local storage (the &#8220;new cookie&#8221;, as discussed <a href="http://aptoma.com/select.star/2009/10/12/aptoma-monday-school-week-42/">last week</a>) will not create any such problems for Varnish.</p>
<h3>2. View / subview caching (Application Caching)</h3>
<p>In <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">MVC-terms</a>, the view is the rendered HTML from the application. Caching the full view would be like the &#8220;page caching&#8221; from above, only in this case done within the application itself. This would overlap with Varnish strategy above. But even though this version would solve the cookie-problem depicted above, it is normally no longer used this way after Varnish came along.</p>
<p>Subview caching, however, can still be of good use. A subview is simply a part of a page. This is useful when you e.g. have Varnish set for 1 minute caching, but you know that parts of the page could easily be cached for an hour without becoming obsolete. Examples include  a seldom changing navigational menu, a generated thumbnail image or page headers and footers. To do subview caching will involve putting your subview data into memcached, file cache or you can achieve something similar using Varnish Edge Side Includes (ESI)</p>
<h3>3. Data caching (Application Caching)</h3>
<p>Data caching is typically done in your &#8220;model-layer&#8221; (again with the <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">MVC</a>). A class-function in your business logic will check memcached if there are cached versions of the data about to be fetched from database before proceeding with the SQL-statement if no such data can be found in cache. Afterward it will update the cache with fresh data. This allows a very fine grained control on cache times on different data. Data which is heavy on the ol&#8217; computer and can be cached for a very long time, is candidate even for being serialized and put into a database for easy recovery upon reboots etc. Involving a database for handling large data sets is also provides you with more sophisticated access, update or delete schemes beyond what the neanderthal key/value database in memcached can offer.</p>
<p>We rely heavily on this strategy in our products, and the strategy is typically a good one for creating robust API&#8217;s. Also, we use it in our in-house framework (Aptoma FrameWork, AFW) for the Autoloader (automatic discovery and loading of classes) where file-paths are stored in memcached for rapid access upon subsequent requests. Used in combination with APC, this provides us with a blazing fast framework technology.</p>
<p>Let&#8217;s take an example</p>
<p>An Event object that handles data in a roster scheduler is stored in the &#8220;events&#8221; database table. To load an event, we have to fetch a lot of extra information relating to it: Employee, department, workplace, conflicts with interfering events, and so on. All this will be very time consuming. Thus, we should store all data to cache for re-use!</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> loadEvent<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
 <span style="color: #666666; font-style: italic;">// Try to fetch the event from Memcache data storage</span>
 <span style="color: #000088;">$event</span> <span style="color: #339933;">=</span> Cache<span style="color: #339933;">::</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Event'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$event</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$event</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #666666; font-style: italic;">// If the Event does not exists in Memcached,</span>
 <span style="color: #666666; font-style: italic;">// we do the conventional, time consuming processing here.</span>
&nbsp;
 <span style="color: #666666; font-style: italic;">// Finally, we do cache the Event for the posterity</span>
 Cache<span style="color: #339933;">::</span><span style="color: #004000;">setObject</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$event</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Event'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #b1b100;">return</span> <span style="color: #000088;">$event</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Usually we use cron-jobs to pre-load these data as well.</p>
<p>A main challenge for this kind of caching-scheme is to prevent data from becoming corrupt. If an interfering event changes, and we fail to validate the cache from the example above, we would be left with bad data in our cache. Keep this in mind when designing your data caching.</p>
<h3>4. <span style="text-decoration: line-through;">Local</span> Client caching</h3>
<p><span style="text-decoration: line-through;">Local</span> Client caching is something as simple as the client itself keeping a version of some data, not asking for a new version from the server. This can be cookies, a CSS-file or any other form of static content (javascript or images).</p>
<p>There are two strategies for client caching :<br />
<strong>a)</strong> force very, very long cache times on the client, and change file names whenever you need the contents of a CSS-file for instance or<br />
<strong>b)</strong> keep cache times low to ensure that the clients asks for an updated version from time to time.</p>
<p>Strategy a) adds complexity to the application level, as you will have to handle file names changing, and changing file names might break external dependencies on the file. However it will ensure that changes to static content is displayed at the clients immediately. <a href="http://developer.yahoo.com/performance/rules.html#expires">Yahoo recommend this strategy</a>. Strategy b) will delay updates of static content until the cache at the client has expired, but will keep things simpler for the programmer and more stable for any external dependencies on the file names.</p>
<h3>5. Query Cache</h3>
<p>SQL-query results are cached in MySQL internally. Configuration at server level can be OFF / ON / DEMAND. An attempted cache lookup with no hits, gives a 20% loss of performance. DEMAND requires use of SELECT <strong>/*SQL CACHE*/, </strong>to force caching. Putting the keyword in comments, will ensure SQL-compatibility with other engines than MySQL.</p>
<p>We recommend using the ON or DEMAND setting on your installation. If you never touched this setting, it is probably set to ON.</p>
<p>If you need to squeeze out every bit of performance available from your application, you should switch to the DEMAND-setting, and review all your SQL-statements and judiciously use the SQL CACHE-trigger. If you have the time and skill to do this, you will benefit from it. You would want to use it on tables with a high percentage of read over write requests. Using SQL-CACHE on tables with a lot of writes will only hurt your overall performance. (<a href="http://aptoma.com/select.star/2009/10/22/mysql-query-cache/">Lars has more to say on the topic of Query Cache</a>)</p>
<h3>Referred technologies</h3>
<ul>
<li><a href="http://varnish.projects.linpro.no/">Varnish</a> &#8211; high-performance HTTP accelerator. (see also <a href="http://varnish.projects.linpro.no/wiki/ESIfeatures">Varnish ESI</a>).</li>
<li><a href="http://www.danga.com/memcached/">Memcache</a> &#8211; high-performance, distributed memory object caching system.</li>
<li><a href="http://php.net/manual/en/book.apc.php">APC</a> &#8211;    caching and optimizing PHP intermediate code.</li>
<li>AFW &#8211; our in-house framework which is tightly coupled and integrated to all of the above technologies. (due for release New BSD License in 2010)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2009/10/22/caching-strategies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MySQL Query Cache</title>
		<link>http://aptoma.com/select.star/2009/10/22/mysql-query-cache/</link>
		<comments>http://aptoma.com/select.star/2009/10/22/mysql-query-cache/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 14:00:09 +0000</pubDate>
		<dc:creator>Lars Hetland</dc:creator>
				<category><![CDATA[Monday School]]></category>
		<category><![CDATA[coding]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=809</guid>
		<description><![CDATA[The following article is an in-depth look at Query Cache, mentioned briefly in our post about Caching Strategies.
With Query Cache, the result set from SELECT queries are cached with the query command itself as key. Meaning that if a SELECT query initially executes in ten seconds, consecutive times the _exact_ (including whitespace, case and more. [...]]]></description>
			<content:encoded><![CDATA[<p>The following article is an in-depth look at Query Cache, mentioned briefly in <a href="http://aptoma.com/select.star/2009/10/21/caching-strategiescaching-strategies/">our post about Caching Strategies</a>.</p>
<p>With Query Cache, the result set from SELECT queries are cached with the query command itself as key. Meaning that if a SELECT query initially executes in ten seconds, consecutive times the _exact_ (including whitespace, case and more. The query must be an identical string.) same query is executed, the server gets an hit in Query Cache and returns the cached data in milliseconds, normally giving performance boosts between a few and many orders of magnitude. QC is a global server setting and has three modes; ON, OFF and DEMAND. Setting QC to OFF disables it, with it to ON makes the server look for a cached result for all SELECT queries while setting it to DEMAND will have the server only do a QC lookup if the query has SQL_CACHE after the SELECT command. It&#8217;s recommended to put this MySQL-only extension in a comment to keep with compatibility with SQL standards. (SELECT /*SQL_CACHE*/ * FROM brille) A QC miss will add up to about 20% overhead compared to the same query executed directly without QC lookup. QC is guaranteed to deliver fresh data as all QC on a table is invalidated when a INSERT, DELETE or UPDATE command is executed on it. This means that for a table with frequent writes, QC on reads will probably decrease performance. On tables with a high number of both reads and writes, setting QC to DEMAND and not use it on queries hitting that table might be a good idea. When actively using query cache on tables with dates it’s also important to write reusable and cacheable queries. Any use of NOW() or equivalent non-deterministic functions will render query cache unused even within the same second, so date and time should be calculated outside of MySQL. When doing so, first analyze the need for an exact query. If you can get away with &lt; 1 minute accuracy, don’t add date( ‘Y-m-d H:i:s’ ) but date( ‘Y-m-d H:i:00′ ) so any identical queries within the same minute will get the cached result. Subselects will not use QC. On high performance applications, QC should be kept in mind when designing the database and queries. Below are two examples where performance characteristics could be radically different:</p>
<p>First table structure:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`users`</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #ff0000;">`id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`username`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">16</span><span style="color: #66cc66;">&#41;</span> collate utf8_danish_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`password`</span> text collate utf8_danish_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`salt`</span> text collate utf8_danish_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`last_time_visited`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'0000-00-00 00:00:00'</span><span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #ff0000;">`username`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`username`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>InnoDB <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8 COLLATE<span style="color: #66cc66;">=</span>utf8_danish_ci;</pre></div></div>

<p>Second table structure:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`users`</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #ff0000;">`id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`username`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">16</span><span style="color: #66cc66;">&#41;</span> collate utf8_danish_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`password`</span> text collate utf8_danish_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`salt`</span> text collate utf8_danish_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #ff0000;">`username`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`username`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>InnoDB <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8 COLLATE<span style="color: #66cc66;">=</span>utf8_danish_ci;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`user_visited`</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #ff0000;">`id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`last_time_visited`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'0000-00-00 00:00:00'</span><span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>InnoDB <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8 COLLATE<span style="color: #66cc66;">=</span>utf8_danish_ci;</pre></div></div>

<p>If the first table was used on a high traffic forum, every time a user loads a page the QC would be invalidated as last_time_visited had to be updated. By denormalization and having two tables where one is often read and the other is often written to, QC on the first table would be kept until a user changed password/username or a new user is registered which is probably less frequent than pageloads.</p>
<p>But the way the SELECT query is created is also important. Lets say you normaly just need the basic information about a user, but every time you visit the users profile, last_time_visited is needed:</p>
<p>First set of queries:<br />
Normal display of user:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #808080; font-style: italic;">/*SQL_CACHE*/</span> id<span style="color: #66cc66;">,</span> username <span style="color: #993333; font-weight: bold;">FROM</span> users <span style="color: #993333; font-weight: bold;">WHERE</span> id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;</pre></div></div>

<p>Display of users profile:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #808080; font-style: italic;">/*SQL_CACHE*/</span> u<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">,</span> u<span style="color: #66cc66;">.</span>username<span style="color: #66cc66;">,</span> uv<span style="color: #66cc66;">.</span>last_time_visited <span style="color: #993333; font-weight: bold;">FROM</span> users <span style="color: #993333; font-weight: bold;">AS</span> u <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> user_visited <span style="color: #993333; font-weight: bold;">AS</span> uv <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span> u<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> uv<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">WHERE</span> u<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;</pre></div></div>

<p>Second set of queries:<br />
Normal display of user:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #808080; font-style: italic;">/*SQL_CACHE*/</span> id<span style="color: #66cc66;">,</span> username <span style="color: #993333; font-weight: bold;">FROM</span> users <span style="color: #993333; font-weight: bold;">WHERE</span> id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;</pre></div></div>

<p>Display of users profile:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #808080; font-style: italic;">/*SQL_CACHE*/</span> id<span style="color: #66cc66;">,</span> username <span style="color: #993333; font-weight: bold;">FROM</span> users <span style="color: #993333; font-weight: bold;">WHERE</span> id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
<span style="color: #993333; font-weight: bold;">SELECT</span> last_time_visited <span style="color: #993333; font-weight: bold;">FROM</span> user_visited <span style="color: #993333; font-weight: bold;">WHERE</span> id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;</pre></div></div>

<p>In the first set, two different queries are used to fetch the same information, the username. This means the second query won&#8217;t be able to use the QC of the first and more frequent query. Also, the often-read table is joined with the often-written which means INSERT, DELETE and UPDATE queries on _both_ tables will clear cache for this query. In the second set of queries, the same query is used two times, increasing the chance of QC hit. And instead of joining the two tables in one query, a second and separate query is executed on the second table, here without the SQL_CACHE keyword. Two queries increases overhead, but the gain in higher cache hit (The first query can even get a hit in a Memcache-lookup) can easily outweigh this.</p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2009/10/22/mysql-query-cache/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Aptoma Monday School, week #42</title>
		<link>http://aptoma.com/select.star/2009/10/12/aptoma-monday-school-week-42/</link>
		<comments>http://aptoma.com/select.star/2009/10/12/aptoma-monday-school-week-42/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 14:57:51 +0000</pubDate>
		<dc:creator>Geir Berset</dc:creator>
				<category><![CDATA[Monday School]]></category>

		<guid isPermaLink="false">http://aptoma.com/select.star/?p=764</guid>
		<description><![CDATA[We&#8217;ve launched a new initiative here at Aptoma, and we have given it the mundane name of &#8216;Aptoma Monday School&#8217; (AMS). We could have been cool and written &#8220;Skool&#8221; or something like that, but we didn&#8217;t.

AMS is basically an intense hour each Monday @ 0900 hours which we dedicate to educate ourselves through presenting and [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve launched a new initiative here at Aptoma, and we have given it the mundane name of &#8216;Aptoma Monday School&#8217; (AMS). We could have been cool and written &#8220;Skool&#8221; or something like that, but we didn&#8217;t.</p>
<p><img class="alignnone size-full wp-image-782" title="Chalkboard and Apple" src="http://aptoma.com/select.star/wp-content/uploads/2009/10/back-to-school.jpg" alt="Chalkboard and Apple" width="560" height="219" /></p>
<p>AMS is basically an intense hour each Monday @ 0900 hours which we dedicate to educate ourselves through presenting and discussing topics of particular interest. We have a business to run, so the topics has to be of practical use as well as educational value. We will try to identify the sweet-spot of balance between learning something fun and inspiring and creating something tangible of value for our customers.</p>
<p>We have decided to share our lecture notes on the Select *-blog (<a href="http://feeds.feedburner.com/aptoma/selectstar">RSS</a>). The theme of choice for now has been the field of &#8220;<strong>HTML5</strong>&#8220;. And we have chosen three topics this week : The <strong>&lt;video&gt;</strong>-element, the <strong>&lt;canvas&gt;</strong>-element and <strong>local storage</strong>.</p>
<h3>1. Video</h3>
<p>The video-element will start to finally integrate videos fully into the web-page. This means that plugin-technologies such as Adobe Flash or Windows Media Player will no longer be required for video. (yes!)</p>
<p><em>&lt;video width=&#8221;854&#8243; height=&#8221;480&#8243; autobuffer controls&gt;<br />
&lt;source src=&#8221;big_buck_bunny_480p_stereo.ogx&#8221; type=&#8221;video/ogg&#8221;&gt;</em><em><br />
&lt;!&#8211; Proceed to define any available fallback formats &#8211;&gt;<br />
&lt;source src=&#8221;big_buck_bunny_480p_h264.mov&#8221;&gt;<br />
Your browser does not support the &lt;code&gt;video&lt;/code&gt; element.<br />
&lt;/video&gt;</em></p>
<p>The video-element will now work as a normal element, providing you with the full power of CSS: You can set the css-attribute opacity to 0.5, and it does what you think it will do. If you have been working with any of the plugin-technologies, you&#8217;ll know that this is a giant leap forward for video.</p>
<p>The browser can render its browser native controls (play/stop/pause/etc.) or be controlled by JavaScript and make use of event listeners and normal DOM-function to make it &#8220;richer&#8221; than what is possible with plugins. This basically means that you can design your player using HTML and JavaScript.</p>
<p><strong>See it in action!</strong></p>
<p><a href="http://youtube.com/html5">Youtube has made an example of use of HTML5/video-element</a>. In this example even animated thumbnails are video-elements displaying how low the resource cost ist. If you did this with Adobe Flash would probably require <a href="http://moarhardware.com">moarhardware.com</a> to keep all the elements on one page together like that.</p>
<p><strong>A few more details for the very interested reader :<br />
</strong></p>
<ul>
<li>&lt;video&gt; might just allow us to do more hardware acceleration and the client computer, and hence have a much smaller toll on system resources than today&#8217;s solution.</li>
<li>Safari supports H.264/AAC, Chrome supports H.264/AAC and OGG/Theora/Vorbis while Firefox and Opera just support the latter.</li>
<li>&lt;video&gt; is supported in Safari, Firefox 3.5, Chrome and a special build of Opera, so we&#8217;re not quite there, yet. But we&#8217;re getting closer!</li>
</ul>
<h3>2. Canvas</h3>
<p>Canvas is another exciting technology which is finally mature for use in most modern web-browsers. Canvas let&#8217;s you do pixel by pixel manipulations on images.</p>
<p>Canvas will be a nice replacement for the most server-side generated images as well as for some Flash graphics. Due to the fact that canvas is rendered by the browser and not as a plugin it can be handled as (almost) as all the other HTML elements .</p>
<p>We&#8217;ll let this example speak for itself : <a href="http://disruptive-innovations.com/zoo/demos/eyes.html">Remove redeye</a>.</p>
<p><strong>You define a canvas like this<br />
</strong> <em>&lt;canvas id=&#8221;myCanvas&#8221; width=&#8217;172&#8242; height=&#8217;172&#8242;&gt;&lt;/canvas&gt;</em></p>
<p><strong>And you will run commands on it like this, to do the funky stuff (presented without any particular context)</strong><em><strong><br />
</strong> var canvas = document.getElementById(&#8220;myCanvas&#8221;);<br />
var context = canvas.getContext(&#8220;2d&#8221;); // 3d not yet supported<br />
context.rotate (secondsAngle);</em><em><br />
context.drawImage (sechand, -4, -52, 8, 57);<strong><br />
</strong>// Rendring text: </em><em><strong><br />
</strong>context.font         = &#8216;italic 50px sans-serif&#8217;;<br />
context.textBaseline = &#8216;top&#8217;;<br />
context.fillText  (&#8216;Hello world!&#8217;, 0, 0);<br />
context.font         = &#8216;bold 30px sans-serif&#8217;;<br />
context.strokeText(&#8216;Hello world!&#8217;, 0, 50);</em></p>
<p><em></em></p>
<p><strong>If you want to dig deeper, try these:</strong></p>
<ul>
<li><a href="http://developer.apple.com/mac/library/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/Canvas.html">http://developer.apple.com/mac/library/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/Canvas.html</a></li>
<li><a href="http://virtuelvis.com/archives/2005/12/canvas-image-manipulation">http://virtuelvis.com/archives/2005/12/canvas-image-manipulation</a></li>
<li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html">http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html</a></li>
</ul>
<h3>3. Local storage</h3>
<p>Local storage is what you&#8217;d think it is. It might be seen as a sophistication of the good ol&#8217; cookie. It solves a couple of it&#8217;s problems, as well. <strong>a)</strong> You can store more data in local storage.<strong> b)</strong> You can use the same local storage between browser tabs and windows <strong>c)</strong> It will be cache-safe, which means that it will not break all your front-end caches (such as Varnish) if used. This is a major improvement for anyone creating high-traffic sites.</p>
<p>The most important functions are</p>
<ul>
<li>localStorage.setItem(key, value)</li>
<li>localStorage.getItem(key)</li>
<li>localStorage.removeItem(key)</li>
<li>localStorage.clear() // Use with caution, it will clear all storage.</li>
</ul>
<p>Local storage will fire events when updated, which means you can monitor the state of the local storage in JavaScript and act upon it with ease.</p>
<h3>Future topics for AMS</h3>
<p>We maintain this wish-list of topics. We provide no guarantees that we&#8217;ll follow the list, but these are the suggested topics as of today.</p>
<ul>
<li>HTML5
<ul>
<li>Canvas / SVG</li>
<li>Video / Audio</li>
<li>Local Storage</li>
<li>Web-forms</li>
<li>Semantics</li>
<li>Worker threads</li>
<li>Offline work</li>
</ul>
</li>
<li>Caching strategies (Memcache, Varnish, Varnish ESI, etc)</li>
<li>JavaScript development guidelines (JSUnit, JS Coding standard, etc)</li>
</ul>
<p>We&#8217;d love to hear any suggestion you might have for topics in the comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://aptoma.com/select.star/2009/10/12/aptoma-monday-school-week-42/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
