<?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>Infrequently Noted &#187; Uncategorized</title>
	<atom:link href="http://infrequently.org/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://infrequently.org</link>
	<description></description>
	<lastBuildDate>Fri, 18 Nov 2011 16:25:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Function-ality</title>
		<link>http://infrequently.org/2011/10/function-ality/</link>
		<comments>http://infrequently.org/2011/10/function-ality/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 09:51:45 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1708</guid>
		<description><![CDATA[I&#8217;m sitting here in Derek Featherstone&#8217;s amazing a11y talk at Fronteers and I feel like I need to follow up the last post with a quick primer on the zen of function for (both of) the spec authors who read this blog. The reason it&#8217;s offensive to the JS hacker for WebIDL to disallow new [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m sitting here in Derek Featherstone&#8217;s <a href="http://fronteers.nl/congres/2011/sessions">amazing a11y talk at Fronteers</a> and I feel like I need to follow up the last post with a quick primer on the zen of <code>function</code> for (both of) the spec authors who read this blog.</p>
<p>The reason it&#8217;s offensive to the JS hacker for WebIDL to disallow <code>new</code> against DOM types &#8212; <em>any</em> of them &#8212; is that it means that it&#8217;s no longer specifying how you&#8217;d describe these types in the primitive we use over here in JS for this sort of thing: functions. This might sound nuts to folks who come from C++ or who spend their time in spec-ese, but there&#8217;s <em>no difference</em> between a plain-old function, a &#8220;constructor&#8221;, and a &#8220;partial&#8221; or &#8220;mixin&#8221; in JS semantics. We use functions for all of them. You can say <code>new function(){ ... }</code> and create an instance of an anonymous &#8220;class&#8221; in JS. You can take the same function and invoke it as a &#8220;regular function&#8221; &#8212; <code>(function(){ ... })();</code> &#8212; and you can use that sort of function as a mixin or <code>partial</code> interface too: <code>new function(){ (function(){ ... }).call(this); ... }</code>. The <em>exact same</em> function object can even act in all of these capacities (although it&#8217;s rare). People use them as they need to, but they all boil down to functions.</p>
<p>What, then, does it mean for something to disallow <code>new</code> against some type for which you can in some otherwise get an instance in JS? The same thing when you can&#8217;t <code>.call()</code> it: <em>it&#8217;s alien</em>. It&#8217;s not a class as we know it, which means that it&#8217;s not a function, and if it&#8217;s not a function&#8230;well, it doesn&#8217;t belong. Fundamentally, it&#8217;s smuggling static semantics into a language that has perfectly good dynamic semantics for the same thing. This strikes at the very heart of what WebIDL is supposed to be for: describing JS types for things implemented somewhere else. By not allowing <code>new</code> and <code>.call()</code> WebIDL is giving JS semantics the bird, asserting that the fact that these things aren&#8217;t JS types makes them <em>better</em> in some way&#8230;and <em>that</em> is a bug, either in the perspective of the spec authors or of the specs themselves.</p>
<p>Luckily, the fix is easy: all WebIDL types should de-sugar to functions. All of them. All the time. No questions asked. That you will be able to use <code>new</code> and <code>.call()</code> and all the rest isn&#8217;t a bug, and it&#8217;s not something to guard against. It&#8217;s just how JavaScript rolls&#8230;and how JavaScript&#8217;s largest, most important library should roll too.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/10/function-ality/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Standards Are Insurance</title>
		<link>http://infrequently.org/2011/09/standards-are-insurance/</link>
		<comments>http://infrequently.org/2011/09/standards-are-insurance/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 19:47:00 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1685</guid>
		<description><![CDATA[I keep getting distracted from writing this long thing by responding to the discussion created by the last short-ish thing, but I wanted to explicitly call out one aspect, namely that standards are a form of insurance. More correctly &#8212; and apologies if this sounds like a Planet Money episode &#8212; vendors sell derivatives contracts [...]]]></description>
			<content:encoded><![CDATA[<p>I keep getting distracted from writing this long thing by responding to the discussion created by the last short-ish thing, but I wanted to explicitly call out one aspect, namely that <em>standards are a form of insurance</em>. </p>
<p>More correctly &#8212; and apologies if this sounds like a <a href="http://www.npr.org/blogs/money/">Planet Money</a> episode &#8212; vendors sell derivatives contracts (insurance) against the proprietary nature of technologies. I.e., as a hedge against winner-take-all dynamics of network effects and the potential for monopoly rent extraction. Adopters of that technology often refuse to buy it at all without the availability of a derivative to cover their risk of lock-in.</p>
<p>The nice bit about these contracts is that the results (price) are free to the public &#8212; ITU and other old-skool orgs are exceptions &#8212; meaning anyone who wants to implement can assess what it&#8217;ll cost, and if they can provide a solution at a lower to-end-user price, they can compete under the same terms. The public nature of the derivative contract can have the effect of lowering the price of the good itself in markets that clear and have many participants.</p>
<p>Standards organizations are correctly understood as middle-men or market-makers for these contracts.</p>
<p><b>Update:</b> It may seem strange to some that derivatives contracts (insurance) can drive prices down, but it happens in many industries. E.g., satellite insurance has done wonders for the commercial launch vehicle industry. And who would fund the construction of new cargo ships if you couldn&#8217;t convince enough people to ship their precious goods? Insurance matters.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/standards-are-insurance/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What A Breakup Would Look Like</title>
		<link>http://infrequently.org/2011/09/what-a-breakup-would-look-like/</link>
		<comments>http://infrequently.org/2011/09/what-a-breakup-would-look-like/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 18:12:05 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1680</guid>
		<description><![CDATA[Karl Dubost asked what a plan would look like for a W3C split along the lines I proposed in my last post. It&#8217;s a fair question, so let me very quickly sketch out straw-men while noting that I would support many alternative plans as well. The shape of the details might matter, but not as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.la-grange.net/karl/">Karl Dubost</a> asked what a plan would look like for a W3C split along the lines I proposed in my <a href="http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/">last post</a>. It&#8217;s a fair question, so let me <em>very</em> quickly sketch out straw-men while noting that I would support many alternative plans as well. The shape of the details might matter, but not as much as movement in the right direction, and I have faith that the W3C members and staff would do a good job of executing on any such plan. Here are some general forms it could take, both of which seem workable to me:</p>
<h3>Spin-Off With Cross-licensing</h3>
<p>Taking many of the W3C&#8217;s activities to a different organization might be traumatic for some members due to IPR concerns. If the members agree that this is the most important consideration, a pure split could be effected, leaving smaller, parallel organizations with identical legal arrangements and identical IPR policies in place. Member organizations would, in a transition period, decide to move their membership to the spin-off, stay with the W3C, or join both (perhaps at a discount?). A contract between the new organizations would allow perpetual cross-licensing of applicable patent rights.</p>
<p>The risk to this plan is that it may not be clear that <em>one</em> new organization would be appropriate &#8212; remember, we&#8217;re talking about many strange bedfellows under the current W3C umbrella &#8212; so perhaps this may only work for whatever center of gravity exists in the spun-off concerns. Smaller efforts (Java-centric APIs, etc.) may want to find other homes.</p>
<h3>Merger</h3>
<p>One or more of the sub-efforts on the block may wish to find a new home in an existing standards organization. For these efforts there is likely to be larger mismatch between processes, IPR policies, etc. than a spin-off would entail, but the benefits to both receivers and members are clear: a viable home for the long term is hard to build, but coming home to &#8220;your people&#8221; isn&#8217;t nearly as difficult. XML standards, for instance, have a long history at OASIS and it&#8217;s unlikely that many members who care primarily about XML at the W3C aren&#8217;t also active there. Transfer of IPR in this case is likely to be more fraught, so contracts which stipulate license from the W3C to these new organizations would also need to include clauses which cause the receiving orgs to exercise similar processes to the ones currently in place for the standards which they receive ownership of. The contract would also need to stipulate that RF never be endangered for new versions of divested specs. I haven&#8217;t thought hard about transfer of membership under this scenario, but pro-rated and discounted membership terms at all merging organizations &#8212; but only for divested activities &#8212; might work.</p>
<p>Whatever path a breakup takes, the W3C should listen to each of the non-web communities it&#8217;s spinning off and work to ensure that their needs are met in the process. There are lots of details I don&#8217;t have time to think through right now, but none of the ones I can identify seem like deal-breakers. The biggest missing piece is the political will to make <em>something</em> happen in the first place.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/what-a-breakup-would-look-like/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Things the W3C Should Stop Doing</title>
		<link>http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/</link>
		<comments>http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 18:36:55 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1661</guid>
		<description><![CDATA[The time has come for the W3C to grab the mantle of the web, shake off its self-doubt, and move to a place where doing good isn't measured by numbers of specs and activities, but by impact for web developers.]]></description>
			<content:encoded><![CDATA[<p><em>This is a quick thought as I&#8217;m working on something much longer (and hopefully more interesting) to be published in the next week or so. Also, I just want to re-iterate that what&#8217;s said here are my own thoughts and not those of Google unless expressly stated otherwise.</em></p>
<p>I&#8217;ve been arguing &#8212; mostly over beers &#8212; for the last year or so that the W3C needs to find a ways to re-focus on the needs of the constituencies that give it credibility; namely web developers and browser vendors. This tends to fall on frustrated W3C staffer ears as individuals might agree but the organization feels the effects of its failures not as a question about how to re-focus around a credible mission but as a short-run funding shortfall. I&#8217;m excited that the new <a href="http://www.w3.org/community/">Community Groups</a> have the potential to help fix some of this by allowing a freer flow of ideas and a more representative expressions of demand, but there&#8217;s the lingering pay-for-play issue that I think is liable to drag the organization back to the status-quo as soon as the excitement and newness of Community Groups wear off.</p>
<p>Now, let me say clearly up front that I don&#8217;t think that standards bodies are charities, nor should they be. People join (in the case of the W3C, &#8220;people&#8221; == &#8220;companies&#8221;, an equivalence that works as US legal fiction but never in the real world) because they&#8217;re expressing their economic interests in agreement on thorny, market-focused issues. The W3C, as an organ, has grown out of an IETF alternative into a critical mediator in the flow of ideas and technology in the web ecosystem. When it fails, we&#8217;re starved of progress because nothing else can easily grow in its place. Bless Hixie and the WHATWG for trying, but the W3C sits on fertile spec and patent rich land. It&#8217;s tough growing in the rocky craigs, particularly without a patent policy.</p>
<p>So, in the spirit of reform, not revolution, I have a proposal, complete with Swiftian modesty:</p>
<h3>At <a href="http://www.w3.org/2011/11/TPAC/">this year&#8217;s TPAC</a>, it should be agreed that the W3C will divest itself of any and all Semantic Web, RDF, XML, Web Services, and Java related activities. SVG can be saved, but only if it re-charters to drop all XML dependencies in the next version.</h3>
<p>Where should these specs and member organizations go to get their itches scratched? I&#8217;m not sure it matters, although it seems likely that OASIS wouldn&#8217;t mind being the go-to place for XML. And there&#8217;s always ECMA, or IETF, or ISO, or&#8230;you get the idea.</p>
<p>Why do such a drastic thing?</p>
<p>Well, it&#8217;s not that drastic, really. The SemWeb folks use the term &#8220;web&#8221; in a hopeful, forward looking way that nobody else does. Their technology is showing promise inside firewalls but their work has near zero relationship to the actual, messy web we swim in every day. The result is that their narrow  constituency isn&#8217;t the one that animates whatever legitimacy the W3C might enjoy, and therefore their influence in the W3C is out of all proportion to their organizational and web-wide value. Sir Tim&#8217;s belief in their goal is noble, but to use the suffix &#8220;web&#8221; on it today is simply wishful thinking. And things that don&#8217;t have anything to do with the web probably don&#8217;t belong at the W3C. Besides, the W3C imprimatur doesn&#8217;t help these specs and groups as much as their advocates might think &#8212; standards bodies aren&#8217;t venues for creating the future after all, only for cleaning it up in response to the messy, explosive process of market-driven evolution. Anyway, being endlessly frustrated that the entire web hasn&#8217;t changed to accomodate some new model even though it has the phrase &#8220;web&#8221; in the name can&#8217;t be fun. Technologies need to find their success where they <em>really do fit</em> and distributed extensibility and semantics might be valuable&#8230;but it hasn&#8217;t been to the web yet. It needs to go.</p>
<p>As for XML, well, it won the enterprise and lost the web. That&#8217;s still success, but it&#8217;s not the web.</p>
<p>Rinse, repeat for RDF, Web Services, and Java.</p>
<p>What would that leave us with? CSS, DOM &#038; JS APIs, HTML, a11y, i18n, and all the other stuff that has legs out on the public web. More to the point, it would have the beneficial effect of re-focusing the organization around getting HTML5 done, getting DOM APIs done that don&#8217;t suck for JavaScript on the altar of IDL &#8220;language neutrality&#8221;, etc.</p>
<p>Organizationally, it would leave the W3C in a much leaner, more focused place. It&#8217;s much easier to build a focused constituency and membership, and the lower cost structure would only help the organization weather hard times. I have high hopes that it can be brutally effective again&#8230;but to get there, it needs to focus, and focus is the process of ignoring things. The time has come for the W3C to grab the mantle of the web, shake off its self-doubt, and move to a place where doing good isn&#8217;t measured by numbers of specs and activities, but by impact for web developers.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
		<item>
		<title>Why &#8220;class&#8221; Doesn&#8217;t Mean What You Think It Means</title>
		<link>http://infrequently.org/2011/09/why-class-doesnt-mean-what-you-think-it-means/</link>
		<comments>http://infrequently.org/2011/09/why-class-doesnt-mean-what-you-think-it-means/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 14:33:30 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1662</guid>
		<description><![CDATA[There&#8217;s a lot of &#8220;don&#8217;t turn it into Java!&#8221; in the comments on my last post, and I feel it needs a response &#8212; and not because I think there&#8217;s anything to like about Java&#8217;s class or type systems (perhaps that they exist at all? I&#8217;m torn on even that). Lets look at some possible [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a lot of <em>&#8220;don&#8217;t turn it into Java!&#8221;</em> in the comments on my last post, and I feel it needs a response &#8212; and not because I think there&#8217;s anything to like about Java&#8217;s class or type systems (perhaps that they exist at all? I&#8217;m torn on even that).</p>
<p>Lets look at some possible ES.next code and walk through how it relates to today&#8217;s equivalent JS:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">module widgets <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">export</span> <span style="color: #003366; font-weight: bold;">class</span> DropDownButton <span style="color: #003366; font-weight: bold;">extends</span> Widget <span style="color: #009900;">&#123;</span>
    constructor<span style="color: #009900;">&#40;</span>attributes<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #003366; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>attributes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">buildUI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    buildUI<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">domNode</span>.<span style="color: #660066;">onclick</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-&gt;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// ...</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Ignoring the semantic improvements of Harmony modules over the module patterns we&#8217;re using today, we can see a pretty straight-up de-sugaring of that to today&#8217;s JS with an emphasis on the many and varied uses of the word <code>function</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> widgets <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>global<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">function</span> DropDownButton<span style="color: #009900;">&#40;</span>attributes<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    Widget.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> attributes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">buildUI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  DropDownButton.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> Object.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>Widget.<span style="color: #660066;">prototype</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
    constructor<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> value<span style="color: #339933;">:</span> DropDownButton <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    buildUI<span style="color: #339933;">:</span>     <span style="color: #009900;">&#123;</span>
      value<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">domNode</span>.<span style="color: #660066;">onclick</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #006600; font-style: italic;">// ...</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>What you should take away from this isn&#8217;t that we&#8217;re turning JS into Java, it&#8217;s that we&#8217;re making it easier to read, <em>AND THAT&#8217;S ALL</em>. Once more for effect: what <em>class</em> means in ES6 is <em>function</em>. Or at least one of the things you currently do with <code>function</code>.</p>
<p>Better yet, we&#8217;re blessing a single pattern which you can use with old-style classes just as easily as you do today. I&#8217;ll leave it as an exercise for you to name all the different class patterns and systems that do nearly the same thing in slightly incompatible ways today. It&#8217;s a very long list.</p>
<p>If you like JS, and you like functions + prototypes (I do!), you have nothing to fear from the sugar we&#8217;re adding in ES6.</p>
<p><b>Update:</b> A lunchtime conversation here at DojoConf today reminded me of perhaps the largest thing that this new system <em>doesn&#8217;t</em> do; ES.next aren&#8217;t tied to a Java-like type system. Many of the conjoined fears of Java come from the very real pain created by a strict, nominal type system, and nobody in the committee is proposing a mistake like that &#8212; least of all me.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/why-class-doesnt-mean-what-you-think-it-means/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Browser Wars (plural)</title>
		<link>http://infrequently.org/2011/03/browser-wars-plural/</link>
		<comments>http://infrequently.org/2011/03/browser-wars-plural/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 16:24:01 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1624</guid>
		<description><![CDATA[In a half hour, I&#8217;m going to be on the Web 2.0 Expo Browser Wars panel with a cast of incredible folks. A couple of weeks back, I had the privilege of doing something similar on a browser panel expertly moderated by Arun Ranganathan. As a part of that panel, Brendan, Lars, Arun, John, and [...]]]></description>
			<content:encoded><![CDATA[<p>In a half hour, I&#8217;m going to be on the <a href="http://www.web2expo.com/webexsf2011/public/schedule/detail/17798">Web 2.0 Expo Browser Wars panel</a> with a cast of incredible folks. A couple of weeks back, I had the privilege of doing something similar on a browser panel expertly moderated by <a href="http://arunranga.com/blog/">Arun Ranganathan</a>.</p>
<p>As a part of that <a href="http://schedule.sxsw.com/events/event_IAP7286">panel, Brendan, Lars, Arun, John, and I</a> all agreed to post a list of links to demos and such that showed off what our latest browsers are doing. Belatedly, here goes:</p>
<hr />
<p>The <a href="http://schedule.sxsw.com/events/event_IAP7286">browser wars panel</a> is designed to be a discussion, so we didn&#8217;t use any kind of presentation media.  So here&#8217;s a list of demos and resources so that you can learn more about stuff we talk about.  Pictures speak volumes about what gets us excited about the web, anyway.</p>
<h3>HTML5, CSS, and JavaScript Demos</h3>
<ul>
<li>
<p><a href="https://demos.mozilla.org/en-US/">The Web O&#8217; Wonder</a> Website works in browsers that support the latest web standards.</p>
</li>
<li>
<p><a href="http://www.beautyoftheweb.com/#/experience/category/coolhtml5">The Beauty of the Web</a> site showcases a bunch of different things with a bit of an <a href="http://windows.microsoft.com/en-US/internet-explorer/products/ie/home">IE9</a> slant.</p>
</li>
<li>
<p><a href="http://studio.html5rocks.com/">HTML5 Rocks</a> showcases a lot of great demos, which work best in <a href="http://www.mozilla.com/en-US/firefox/RC/">Firefox 4</a> and the latest <a href="http://www.google.com/chrome">Chrome</a> (but the site uses feature detection, so much of it will work in <a href="http://windows.microsoft.com/en-US/internet-explorer/products/ie/home">IE9</a> and <a href="http://www.apple.com/safari/">Safari</a>.).</p>
</li>
<li>
<p><a href="http://www.foursquareplayground.com/">FourSquare Playground</a> has a strong <a href="http://windows.microsoft.com/en-US/internet-explorer/products/ie/home">IE9</a> bias, but showcases HTML5.</p>
</li>
<li>
<p><a href="http://www.ietestdrive.com/">IE Test Drive</a>.  Need I say more about bias?  Showcases HTML5, with the promise of some demos that may work cross-browser.</p>
</li>
<li>
<p>Here&#8217;s <a href="http://arunranga.com/presentations/India2010Presentations/Feb2010/BangaloreDevDay.html">a presentation I gave</a>, which may actually have a Firefox bias, given that I showcased technologies that were &#8220;Moz&#8221; prefixed (e.g. <a href="https://developer.mozilla.org/en/DOM/MozOrientation">MozOrientation</a>).  Still, shows off some great demos in a variety of arena (<a href="https://developer.mozilla.org/en/Using_geolocation">Geolocation</a>, etc.).</p>
</li>
</ul>
<h3>WebGL Demos</h3>
<p>To get maximum mileage out of these, you&#8217;ll want a fast PC with the latest Chrome or Firefox.</p>
<ul>
<li>
<p><a href="http://www.ambiera.com/copperlicht/demos.html">The CopperLicht Stuff from Ambiera</a> blows my mind every time.</p>
</li>
<li>
<p><a href="http://videos.mozilla.org/serv/mozhacks/flight-of-the-navigator/">Flight of the Navigator</a> is a really compelling mix of different elements. </p>
</li>
<li>
<p><a href="https://mozillademos.org/demos/remixingreality/demo.html">Remixing Reality</a> is really compelling demo of the use of models.</p>
</li>
<li>
<p><a href="http://www.khronos.org/webgl/wiki/Demo_Repository">The WebGL Demo Repository</a> at Khronos contains demos that are classic GL ones (that 3D programmers are all well familiar with).</p>
</li>
</ul>
<h3>Resources</h3>
<ul>
<li>
<p><a href="http://caniuse.com/">Can I Use</a> provides incredibly useful feature matrices to determine which browser supports what in the HTML5 and CSS arena.</p>
</li>
<li>
<p><a href="http://www.quirksmode.org/">Quirksmode</a> is the go-to place for compatibility tables.</p>
</li>
<li>
<p><a href="http://hacks.mozilla.org/">Hacks</a> is Mozilla&#8217;s showcase for articles, demos, and API updates.</p>
</li>
<li>
<p><a href="http://www.html5rocks.com/">HTML5 Rocks</a> features great stuff about HTML5, and includes code snippets and documentation for developers.</p>
</li>
<li>
<p><a href="http://www.amazon.com/HTML5-Now-Step-Step-Tutorial/dp/0321719913">HTML5 Now</a> is <a href="http://www.tantek.com/">Tantek Celik&#8217;s</a> book on the subject.</p>
</li>
<li>
<p><a href="http://books.alistapart.com/products/html5-for-web-designers">HTML5 for Web Designers</a> is <a href="http://www.adactio.com/">Jeremy Keith&#8217;s</a> book on the subject.</p>
</li>
<li>
<p><a href="http://www.brucelawson.co.uk/2010/introducing-html5-lands/">Bruce Lawson and Remy Sharp&#8217;s HTML5 Lands</a></p>
</li>
<li>
<p><a href="http://learningwebgl.com/blog/">Learning WebGL</a> and the <a href="http://learningwebgl.com/cookbook/index.php/Main_Page">WebGL Cookbook</a> are great sites to learn WebGL</p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/03/browser-wars-plural/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Performance Innumeracy &amp; False Positives</title>
		<link>http://infrequently.org/2011/02/on-performance-innumeracy-false-positives/</link>
		<comments>http://infrequently.org/2011/02/on-performance-innumeracy-false-positives/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 18:49:41 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1575</guid>
		<description><![CDATA[tl;dr version: the web is waaaay too slow, and every time you write something off as &#8220;just taking a couple of milliseconds&#8221;, you&#8217;re part of the problem. Good engineering is about tradeoffs, and all engineering requires environmental assumptions &#8212; even feature testing. In any case, there are good, reliable ways to use UA detection to [...]]]></description>
			<content:encoded><![CDATA[<p><em>tl;dr version: the web is waaaay too slow, and every time you write something off as &#8220;just taking a couple of milliseconds&#8221;, you&#8217;re part of the problem. Good engineering is about tradeoffs, and all engineering requires environmental assumptions &#8212; even feature testing. In any case, there are good, reliable ways to use UA detection to speed up feature tests in the common case, which I&#8217;ll show, and to which the generic arguments about UA <b>vs.</b> feature testing simply don&#8217;t apply. We can and should go faster. <b>Update:</b> <a href="http://www.nczonline.net/blog/2011/02/08/on-ua-sniffing-browser-detection-and-alexs-post/">Nicholas Zackas explains it all, clearly, in measured form. Huzzah!</a></em></p>
<h2>Performance Innumeracy</h2>
<p>I want to dive into concrete strategies for low-to-no false positive UA matching for use in caching feature detection results, but first I feel I need to walk back to some basics since I&#8217;ve clearly lost some people along the way. Here are some numbers every developer (of any type) should know, borrowed from <a href="http://norvig.com/21-days.html">Peter Norvig&#8217;s indispensable &#8220;Teach Yourself To Program In Ten Years&#8221;</a>:</p>
<blockquote><p>
Approximate timing for various operations on a typical PC:<br />
<table class="callout">
<tr>
<td>execute typical instruction</td>
<td align=right> 1/1,000,000,000 sec = 1 nanosec
</td>
</tr>
<tr>
<td>fetch from L1 cache memory</td>
<td align=right> 0.5 nanosec
</td>
</tr>
<tr>
<td>branch misprediction</td>
<td align=right> 5 nanosec
</td>
</tr>
<tr>
<td>fetch from L2 cache memory</td>
<td align=right> 7 nanosec
</td>
</tr>
<tr>
<td>Mutex lock/unlock</td>
<td align=right> 25 nanosec
</td>
</tr>
<tr>
<td>fetch from main memory</td>
<td align=right> 100 nanosec
</td>
</tr>
<tr>
<td>send 2K bytes over 1Gbps network</td>
<td align=right> 20,000 nanosec
</td>
</tr>
<tr>
<td>read 1MB sequentially from memory</td>
<td align=right> 250,000 nanosec
</td>
</tr>
<tr>
<td>fetch from new disk location (seek)</td>
<td align=right> 8,000,000 nanosec
</td>
</tr>
<tr>
<td>read 1MB sequentially from disk</td>
<td align=right> 20,000,000 nanosec
</td>
</tr>
<tr>
<td>send packet US to Europe and back</td>
<td align=right> 150 milliseconds = 150,000,000 nanosec
</td>
</tr>
</table>
<p>
</p>
</blockquote>
<p>That data&#8217;s a bit old &#8212; 8ms is optimistic for a HD seek these days, and SSD changes things &#8212; but the orders of magnitude are relevant. For mobile, we also need to know:</p>
<table class="callout">
<tr>
<td>fetch from flash storage</td>
<td align=right>1,300,000 nanosec</td>
</tr>
<tr>
<td>60hz time slice</td>
<td align=right>16,000,000 nanosec</td>
</tr>
<tr>
<td>send packet outside of a (US) mobile carrier network and back</td>
<td align=right>80-800 milliseconds = 80,000,000 &#8211; 800,000,000 nanosec</td>
</tr>
</table>
<p>The 60hz number is particularly important. To build UI that feels not just fast, but instantly responsive, we need to be yielding control back to our primary event loop in <em>less than 16ms</em>, all the time, every time. Otherwise the UI will drop frames and the act of clicking, tapping, and otherwise interacting with the app will seem &#8220;laggy&#8221; or &#8220;janky&#8221;. Framing this another way, anything your webapp blocks on for more than 16ms is the enemy of solid, responsive UI.</p>
<p>Why am I blithering on and on about this? Because some folks continue to mis-prioritize the impact of latency and performance on user satisfaction. Google (my employer, who does not endorse this blog or my private statements in any way) has <a href="http://code.google.com/speed/files/delayexp.pdf">shown that seemingly minor increases in latency directly impact user engagement</a> and that <a href="http://glinden.blogspot.com/2006/11/marissa-mayer-at-web-20.html">major increases in latency (> 500ms) can reduce traffic and revenue <em>significantly</em></a>. Latency then, along with responsiveness (do you drop below 60hz?), is a key metric for measuring the quality of an web experience. It&#8217;s no accident that Google employs <a href="http://stevesouders.com/">Steve Souders</a> to help evangelize the cause of improving performance on the web, and has gone so far as to build products like Chrome &amp; V8 who have as a core goal to the web faster. A faster web is a better web. Full stop.</p>
<p>That&#8217;s why I get so deeply frustrated when we get <a href="http://farukat.es/journal/2011/02/499-lest-we-forget-or-how-i-learned-whats-so-bad-about-browser-sniffing">straw-man based, data-challenged advocacy</a> from the maintainers of <a href="http://www.modernizr.com/">important bits of infrastructure</a>:</p>
<blockquote><p>
This stuff is far from easy to understand; even just the basics of feature detection versus browser detection are quite confusing to some people. That’s why we make libraries for this stuff (and, use browser inference instead of UA sniffing). These are the kind of efforts that we need, to help move the web forward as a platform; what we don’t need is more encouragement for UA sniffing as a general technique, only to save a couple of milliseconds. Because I can assure you that the Web never quite suffered, technologically, from taking a fraction of a second longer to load.
</p></blockquote>
<p>What bollocks. Not only did I not encourage UA sniffing &#8220;as a general technique&#8221;, latency does in fact hurt sites and users &#8212; all the time, every day. And we&#8217;re potentially not talking about &#8220;a couple of milliseconds&#8221; here. Remember, in the context of mobile devices, the CPUs we&#8217;re on are single-core and clocked in the 500mhz-1ghz range, which directly impacts the performance of single-threaded tasks like layout and JavaScript execution &#8212; which by the way happen <em>in the same thread</em>. In my last post I said:</p>
<blockquote><p>
&#8230;if you’re a library author or maintainer, please please please consider the costs of feature tests, particularly the sort that mangle DOM and or read-back computed layout values
</p></blockquote>
<p>Why? Because many of these tests inadvertently force layout and style re-calculation. See for instance <a href="https://github.com/phiggins42/has.js/blob/master/detect/events.js#L14">this snippet from <code>has.js</code></a>:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>has.<span style="color: #660066;">isHostType</span><span style="color: #009900;">&#40;</span>input<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  input.<span style="color: #660066;">type</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;checkbox&quot;</span><span style="color: #339933;">;</span>
  input.<span style="color: #660066;">style</span>.<span style="color: #660066;">display</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;none&quot;</span><span style="color: #339933;">;</span>
  input.<span style="color: #660066;">onclick</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// ...</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">try</span><span style="color: #009900;">&#123;</span>
    de.<span style="color: #660066;">insertBefore</span><span style="color: #009900;">&#40;</span>input<span style="color: #339933;">,</span> de.<span style="color: #660066;">firstChild</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    input.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    de.<span style="color: #660066;">removeChild</span><span style="color: #009900;">&#40;</span>input<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">catch</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
  <span style="color: #006600; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Everything looks good. The element is <code>display: none;</code> so it shouldn&#8217;t be generating render boxes when inserted into the DOM. Should be cheap, right? Well, lets see what happens in WebKit. Debugging into a simple test page with equivalent code shows that part of the call stack looks like:</p>
<pre>
#0	0x0266267f in WebCore::Document::recalcStyle at Document.cpp:1575
#1	0x02662643 in WebCore::Document::updateStyleIfNeeded at Document.cpp:1652
#2	0x026a89fd in WebCore::MouseRelatedEvent::receivedTarget at MouseRelatedEvent.cpp:152
#3	0x0269df03 in WebCore::Event::setTarget at Event.cpp:282
#4	0x026af889 in WebCore::Node::dispatchEvent at Node.cpp:2604
#5	0x026adbcb in WebCore::Node::dispatchMouseEvent at Node.cpp:2885
#6	0x026ae231 in WebCore::Node::dispatchSimulatedMouseEvent at Node.cpp:2816
#7	0x026ae3f1 in WebCore::Node::dispatchSimulatedClick at Node.cpp:2837
#8	0x02055bb5 in WebCore::HTMLElement::click at HTMLElement.cpp:767
#9	0x022587e6 in WebCore::HTMLInputElementInternal::clickCallback at V8HTMLInputElement.cpp:707
...
</pre>
<p><code>Document::recalcStyle()</code> can be <em>very</em> expensive, and unlike painting, it blocks input and other execution. And the cost is at page loading is likely to be much higher than other times as there will be significantly more new styles streamed in from the network to satisfy for each element in the document when this is called. This isn&#8217;t a full layout, but it&#8217;s most of the price of one. Now, you can argue that this is a WebKit bug and I&#8217;ll agree &#8212; synthetic clicks should probably skip this &#8212; but I&#8217;m just using this as an illustration to show that what browsers are doing on your behalf isn&#8217;t always obvious. Once this bug is fixed, this test may indeed be nearly free, but it&#8217;s not today. Not by a long shot.</p>
<p>Many layouts in very deep and &#8220;dirty&#8221; DOMs can take ten milliseconds or more, and if you&#8217;re doing it from script, you&#8217;re causing the system to do lots of work which it&#8217;s probably going to need to throw away later when the rest of your markup and styles show up.  Your average, dinky test harness page likely under-counts the cost of these tests, so when someone tells me &#8220;oh, it&#8217;s only 30ms&#8221;, not only do my eyes bug out at the double-your-execution-budget-for-anything number, but also the knowledge that in the real world, it&#8217;s probably a LOT worse. Just imagine this happening in a deep DOM on a low-end ARM-powered device where memory pressure and a single core are conspiring against you.</p>
<h2>False Positives</h2>
<p>My last post concerned how you can build a cache to eliminate many of these problems <b>if and only if you build UA tests that don&#8217;t have false positives</b>.  Some commenters can&#8217;t seem to grasp the subtlety that I&#8217;m <em>not</em> advocating for the same sort of lazy substring matching that has deservedly gotten such a bad rap.</p>
<p>So how would we build less naive UA tests that can have feature tests behind them as fallbacks? Lets look at some representative UA strings and see if we can&#8217;t construct some tests for them that give us sub-version flexibility but won&#8217;t pass on things that aren&#8217;t <em>actually</em> the browsers in question:</p>
<p>IE 6.0, Windows:</p>
<pre>
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
</pre>
<p>FF 3.6, Windows:</p>
<pre>
Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.13) Firefox/3.6.13
</pre>
<p>Chrome 8.0, Linux:</p>
<pre>
Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Ubuntu/10.10 Chromium/8.0.552.237 Chrome/8.0.552.237 Safari/534.10
</pre>
<p>Safari 5.0, Windows:</p>
<pre>
Mozilla/5.0 (Windows; U; Windows NT 6.1; sv-SE) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4
</pre>
<p>Some features start to jump out at us. The &#8220;platform&#8221; clauses &#8212; that bit in the parens after the first chunk &#8212; contains a lot of important data and a lot of junk. But the important stuff always comes first. We&#8217;ll need to allow but ignore the junk. Next, stuff after platform clauses is good, has defined order, and can be used to tightly form a match for browsers like Safari and Chrome. With this in mind, we can create some regexes that don&#8217;t allow much in the way of variance but do allow sub-minor version to match so we don&#8217;t have to update these every month or two:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">IE60 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/4\.0 \(compatible; MSIE 6\.0; Windows NT \d\.\d(.*)\)$/</span><span style="color: #339933;">;</span>
FF36 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(Windows; U;(.*)rv\:1\.9\.2.(\d{1,2})\)( Gecko\/(\d{8}))? Firefox\/3\.6(\.\d{1,2})?( \(.+\))?$/</span><span style="color: #339933;">;</span>
CR80 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \((Windows|Macintosh|X11); U;.+\) AppleWebKit\/534\.10 \(KHTML\, like Gecko\) (.+)Chrome\/8\.0\.(\d{3})\.(\d{1,3}) Safari\/534\.10$/</span><span style="color: #339933;">;</span></pre></div></div>

<p>These look pretty wordy, and they are, because they&#8217;re designed NOT to let through things that we don&#8217;t really understand. This isn&#8217;t just substring matching on the word &#8220;WebKit&#8221; or &#8220;Chrome&#8221;, this is a tight fit against the structure of the entire string. If it doesn&#8217;t fit, we don&#8217;t match, and our cache doesn&#8217;t get pre-populated. Instead, we do feature detection. Remember, false positives here are the enemy, so we&#8217;re using &#8220;^&#8221; and &#8220;$&#8221; matches to ensure that the string has the right structure all the way through, not just at some random point in the middle, which UA&#8217;s that parade around as other browsers tend to do.</p>
<p> Here&#8217;s some sample code that incorporates the approach:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>global<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// The map of available tests</span>
    <span style="color: #003366; font-weight: bold;">var</span> featureTests <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> audio <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">return</span> audio <span style="color: #339933;">&amp;&amp;</span> audio.<span style="color: #660066;">canPlayType</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009966; font-style: italic;">/*...*/</span> <span style="color: #009900;">&#125;</span>
        <span style="color: #006600; font-style: italic;">// ...</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// A read-through cache for test results.</span>
    <span style="color: #003366; font-weight: bold;">var</span> testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// An (exported) function to run/cache tests</span>
    global.<span style="color: #660066;">ft</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> testCache<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> testCache<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;undefined&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span>
                                    featureTests<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span>
                                    testCache<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Tests for 90+% of current browser usage</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> ua <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>global.<span style="color: #660066;">navigator</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> global.<span style="color: #660066;">navigator</span>.<span style="color: #660066;">userAgent</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// IE 6.0/WinXP:</span>
    <span style="color: #003366; font-weight: bold;">var</span> IE60 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/4\.0 \(compatible; MSIE 6\.0; Windows NT \d\.\d(.*)\)$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>IE60<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// IE 7.0</span>
    <span style="color: #006600; font-style: italic;">// ...</span>
    <span style="color: #006600; font-style: italic;">// IE 8.0</span>
    <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// IE 9.0 (updated with fix from John-David Dalton)</span>
    <span style="color: #003366; font-weight: bold;">var</span> IE90 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(compatible; MSIE 9\.0; Windows NT \d\.\d(.*)\)$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>IE90<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Firefox 3.6/Windows</span>
    <span style="color: #003366; font-weight: bold;">var</span> FF36 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(Windows; U;(.*)rv\:1\.9\.2.(\d{1,2})\)( Gecko\/(\d{8}))? Firefox\/3\.6(\.\d{1,2})?( \(.+\))?$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>FF36<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Chrome 8.0</span>
    <span style="color: #003366; font-weight: bold;">var</span> CR80 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \((Windows|Macintosh|X11); U;.+\) AppleWebKit\/534\.10 \(KHTML\, like Gecko\) (.+)Chrome\/8\.0\.(\d{3})\.(\d{1,3}) Safari\/534\.10$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>FF36<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Safari 5.0 (mobile)</span>
    <span style="color: #003366; font-weight: bold;">var</span> S5MO <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(iPhone; U; CPU iPhone OS \w+ like Mac OS X; .+\) AppleWebKit\/(\d{3,})\.(\d+)\.(\d+) \(KHTML\, like Gecko\) Version\/5\.0(\.\d{1,})? Mobile\/(\w+) Safari\/(\d{3,})\.(\d+)\.(\d+)$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>FF36<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>New versions of browsers won&#8217;t match these tests, so we won&#8217;t break libraries in the face of new UAs &#8212; assuming the feature tests also don&#8217;t break, which is a big if in many cases &#8212; and we can go faster for the majority of users. Win.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/02/on-performance-innumeracy-false-positives/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>On The Care And Feeding of Spinning Disks</title>
		<link>http://infrequently.org/2011/01/on-the-care-and-feeding-of-spinning-disks/</link>
		<comments>http://infrequently.org/2011/01/on-the-care-and-feeding-of-spinning-disks/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 00:58:24 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1531</guid>
		<description><![CDATA[or: Why I spent last summer rebooting Windows or: How to compress several months of research into 50 lines of code and unblock a product launch, for fun and profit. Home parlor entertainment edition. Fun for all ages. Warranty void if seal broken. Offer not available in some states. Now that others have found the [...]]]></description>
			<content:encoded><![CDATA[<p>or:<br />
<h2>Why I spent last summer rebooting Windows</h2>
<p>or:<br />
<h3>How to compress several months of research into 50 lines of code and unblock a product launch, for fun and profit. Home parlor entertainment edition. Fun for all ages. Warranty void if seal broken. Offer not available in some states.</h3>
<p>Now that <a href="http://twitter.com/#!/shaver/status/28970313320505345">others have found</a> the <a href="http://twitter.com/#!/paulrouget/status/28978459631943680">same technique</a> that I <a href="http://code.google.com/p/chromium/issues/detail?id=45510">used to drop Chrome and Chrome Frame cold start times by more than 2/3</a> last summer, I feel compelled to explain what&#8217;s going on. Particularly as there seems to be <a href="http://news.ycombinator.com/item?id=2131524">some confusion over in the Hacker News thread</a>.</p>
<p>First, a couple of notes and caveats. SSDs are coming (see: ChromeOS, iOS, etc.), and in an SSD world, none of what follows will matter. Some of it could even hurt you. Other concerns &#8212; drive-internal parallelism, bus bandwidth/latency, and the amounts of crapware (that&#8217;s you, Sophos/Bit9/etc.) between your driver and your <code>LoadLibrary</code> call &#8212; are going to dominate. Also note that what I&#8217;m about to say is app specific. If you want your app to start faster, collect data on real-world systems and go from there. Cargo-cult hacks at your own peril.</p>
<p>Right then, spinning disks.</p>
<p>Good programs start fast, and that includes when you start them just after the OS has started. In this state, many of the caches the OS populates on your behalf are unlikely to be full of goodies that&#8217;ll help you start faster, so you pay full freight for all of your dependencies. This is called a &#8220;cold start&#8221;. When you start cold you have to go get everything you need from disk. Usually spinning disk. With > 10ms average latencies for random reads. Ouch.</p>
<p>For a sense of scale, consider that warm starts of Chrome (on Windows) take just ~200ms. That&#8217;s ~200ms for both the browser and renderer processes. 20 random reads from disk <em>double</em> that. Last summer, depending on OS version, disk speed, and amount of Prefetch/SuperFetch training cold starts ranged from 2000-3700ms. Fortunately, browsers are the sorts of things that users tend to keep open, and if they close, re-open later in the same session. Cold start hurts, but it&#8217;s not most user&#8217;s primary experience of a browser.</p>
<p>But that doesn&#8217;t hold for a plugin, particularly one that isn&#8217;t already ubiquitous. Yes, Flash loads quickly, but for most sites it starts fast because some other site had previously loaded it. Cold start matters even more for Chrome Frame. You&#8217;ve already started your browser, so why is this page taking so long to come in? It&#8217;s not enough that the network response is being buffered and the page will feel instant when the renderer finally starts&#8230;we need pixels on screen <em>stat</em>. Hence began my summer of rebooting. We couldn&#8217;t ship Chrome Frame to Stable until cold start was sub-second.</p>
<p>Using custom logging via <a href="http://blogs.microsoft.co.il/blogs/sasha/archive/2008/03/15/xperf-windows-performance-toolkit.aspx">ETW</a> as a starting point, I quickly found that most of the time spent in Chrome startup wasn&#8217;t going to subprocess or thread creation, cache loading, profile reading, or any of the other obvious big-ticket items. Tremendous discipline has been enforced in the Chromium codebase, ensuring that things which might otherwise block startup tend to happen asynchronously, keeping your experience responsive.</p>
<p>What&#8217;s left? ETW, <a href="http://code.google.com/p/sawbuck/">Sawbuck</a> and <a href="http://msdn.microsoft.com/en-us/performance">XPerf</a> eventually showed that we were thrashing disk for lots of little 16-64K reads into <code>chrome.dll</code>. Why not 4K, the size of single page? The Windows memory manager uses a read-ahead optimization when a hard fault occurs. That is to say, when your program tries to execute some bit of code from a library that isn&#8217;t yet in memory, the memory manager will go get the bits that correspond to the code in question, plus a little. Compilers optimize for code locality so you&#8217;re probably going to need the other pages too. Read-ahead (probably) saves you another expensive seek. If you don&#8217;t use those pages, no biggie. Windows is smart enough to prioritize caches. Lots of little 16-64K reads (aka: random I/O!) matched up with the hard page fault data&#8230;bingo. Even with <a href="https://www.microsoft.com/india/windows/windows-vista/features/superfetch.aspx">SuperFetch doing its thing on modern Windows versions</a>, we were seeing lots of slow (>10ms on 5400rpm disk) reads thanks to hard page faults.</p>
<p>Why were we getting these faults? To be entirely honest, we never quite figured this out. SuperFetch/PreFetch do their thing before your program ever hits it&#8217;s CRT main (the very first program-supplied entry point), meaning frequently used pages should already be available. Part of the reason they weren&#8217;t might be the different patterns of access between the Chrome Browser and Renderer processes. The same binary (<code>chrome.exe</code>) and main library (<code>chrome.dll</code>) are used for both, but the bits that each use are pretty radically different. There&#8217;s no access to WebKit code from the Browser process, e.g., but that&#8217;s most of what the Renderer uses. Other theories included some cap on the number of pages that SuperFetch will remember and log. Whatever the reason, fault location graphs showed a pretty violent thrashing toward the top end of <code>chrome.dll</code>.</p>
<p>Idea time: how can we pull all of the pages into the standby list &#8212; the bit of the Virtual Memory cache with the lowest priority &#8212; with a single seek, i.e. one big sequential read? What can we do to slurp the entire DLL into memory so that when the program needs some bit of the library, it gets it from <em>memory</em>, not from spinning (read &#8220;slow&#8221;) disk?</p>
<p>We tried loading the library and walking the pages sequentially. No joy&#8230;well, not much. Certainly not enough. More on that in a second. What about pulling the DLL into the disk cache? Hrmmm. A quick test showed that this worked <em>great</em> on Windows Vista. Just <code>fread</code> the sucker in and <em>boom</em>. ~750ms cold starts!</p>
<p>Except on XP. Balls.</p>
<p>Seemingly the memory manager bypasses the disk cache for faults on XP. Back to the bat-DLL-memory-walk approach, Batman! Yes, this works on XP, albiet with some caveats &#8212; namely that it&#8217;s slower than the other method. We still get stalls and slow seeks, but things improve to the 1300ms range. Average cold starts cut in half. We&#8217;ll take it. The final patch isn&#8217;t pretty, but it does something like what we want. See <a href="http://src.chromium.org/viewvc/chrome/trunk/src/base/file_util_win.cc?view=markup">this file</a>, look for <code>PreReadImage</code> which gets used in Chromium&#8217;s <code>WinMain</code> which does custom DLL loading <a href="http://src.chromium.org/svn/trunk/src/chrome/app/client_util.cc">here</a>, and only on the first (parent, aka, browser) process that&#8217;s created. Voila! Really, really fast starts nearly everywhere.</p>
<p>So, is doing this a good idea?</p>
<p>It&#8217;s not a slam dunk. For users with SSDs, this is more data than they strictly need, possibly slowing starts marginally for them. We&#8217;ll probably have to revisit this at some point. Also, the Vista+ approach potentially pollutes the disk caches. Not great, but at least the pages in questions won&#8217;t cause unnecessary thrashing unless the system is <em>already</em> under memory pressure in which case, the impending startup operations (allocating enough heap for V8, renderer process startup, etc.) are going to hurt no matter what. Also, we&#8217;re not exactly sipping data here. As the size of <code>chrome.dll</code> grows, so will the time required to pull it across the bus, even if the reads are serial. On my most recent dev channel rev, that&#8217;s a 23MB DLL, so if we get 75-100MB/s across the bus (optimistic for these old drives), we&#8217;re looking at a couple of hundred milliseconds just spent reading. Beats a tons of random seeks, but it&#8217;s still not great. Ideally we&#8217;d be able to use PGO/WPO to scope down the amount we <em>really</em> need to read by clumping early-use stuff towards the front of the binary, but so far this hasn&#8217;t panned out thanks to the aforementioned multi-process/single-dll thing. Turns out binary re-writing on Windows isn&#8217;t trivial. Perhaps the biggest down-side is that the XP experience isn&#8217;t ideal yet, and users on XP are most likely to have neither SSDs nor particularly speedy spinning disks. They need the help most. We were able to do something for them thanks to some dark magic in the Windows XP Prefetch system, but that&#8217;s a tale for another day. Suffice to say I now have tremendous respect for the folks who built these systems. Some parts of Windows truly are beautiful.</p>
<p>All in all, this hack has panned out in the real world in a pretty compelling way. Our start time histograms show the improvement in the real world (thanks to all of you who turned on reporting!), and Chrome Frame was able to ship to Stable last fall after we were relatively certain that we weren&#8217;t degrading overall system performance for users.</p>
<p>If you&#8217;ve read all of this, I hope that for your sake it&#8217;s with a sense of historical bemusement. What? They didn&#8217;t all have SSDs/quantum-rent-an-exabytes? Pssh. How did they get by? Well, now you know. One slow reboot of Windows at a time.</p>
<p><b>Bootnote</b>: I should mention that it wasn&#8217;t as straight line to suss out what actually happens in a cold start, pin down causality, understand the differences between XP and Vista+, and convince ourselves with real-world data that this was really our best option. It took a long time. Also, at some point, I stopped borrowing Amit&#8217;s copies of <a href="http://www.amazon.com/Microsoft-Windows-Internals-4th-Server/dp/0735619174">Windows Internals 4</a> and <a href="http://www.amazon.com/Windows%C2%AE-Internals-Including-Windows-PRO-Developer/dp/0735625301">Windows Internals 5</a> and bought my own. You&#8217;ll need both if you still work with XP. Recommended.</p>
<p><b>Footnote to the Bootnote</b>: Obvious Windows Hacker question: why not just do something like read in the DLL from the GCF BHO when you start up? Y&#8217;all get your BHO component loaded at IE launch, after all. </p>
<p>Good thought, Obvious Windows Hacker! Sadly, this is evil&#8230;or at least not very sporting. Even with low-priority I/O on Vista+, it&#8217;s sort of punitive to go do tons of I/O near when the user is probably starting to browse sites that might not make use of our BHO-based goodness, don&#8217;t you think? Besides, if we can get an honest startup win, why cheat? Honest wins pay off for both Chrome and Chrome Frame, which is doubly awesome.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/01/on-the-care-and-feeding-of-spinning-disks/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>In which I eat crow.</title>
		<link>http://infrequently.org/2010/12/in-which-i-eat-crow/</link>
		<comments>http://infrequently.org/2010/12/in-which-i-eat-crow/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 21:23:48 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crow]]></category>
		<category><![CDATA[meaculpa]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1525</guid>
		<description><![CDATA[Ok, ok. I&#8217;ve done my bitching and moaning, for years in person and more recently in blog form. I&#8217;ve listened to the interminable discussions at conferences about how everyone knows exactly what&#8217;s wrong with Twitter and how terribly hard it is to be so popular, and to this day I&#8217;ve escaped such a fate &#8212; [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, ok. I&#8217;ve done my bitching and moaning, for years in person and more recently in <a href="http://infrequently.org/2010/09/twitter-by-the-back-of-a-napkin/">blog form</a>. I&#8217;ve listened to the interminable discussions at conferences about how everyone knows exactly what&#8217;s wrong with Twitter and how terribly hard it is to be so popular, and to this day I&#8217;ve escaped such a fate &#8212; to the extent that Pete even made a <a href="http://twitter.com/#!/fakealexrussell">fake me</a> who, true to form, is nearly as infrequent a poster as I am here. But no longer. Behold! An empty, lame <a href="http://twitter.com/#!/slightlylate">n00b account</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/12/in-which-i-eat-crow/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Glen&#8217;s (Even More) Internet Famous!</title>
		<link>http://infrequently.org/2010/12/glens-even-more-internet-famous/</link>
		<comments>http://infrequently.org/2010/12/glens-even-more-internet-famous/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 04:20:28 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1519</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><iframe title="YouTube video player" class="youtube-player" type="text/html" width="560" height="340" src="http://www.youtube.com/embed/lm-Vnx58UYo?hd=1" frameborder="0"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/12/glens-even-more-internet-famous/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing Catch-Up</title>
		<link>http://infrequently.org/2010/11/playing-catch-up/</link>
		<comments>http://infrequently.org/2010/11/playing-catch-up/#comments</comments>
		<pubDate>Fri, 19 Nov 2010 15:17:35 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1516</guid>
		<description><![CDATA[Seems events are overtaking even my most sarcastic musings. Too bad the Dems are doing this something like a year too late. They find their stones now? Oy.]]></description>
			<content:encoded><![CDATA[<p>Seems <a href="http://tpmdc.talkingpointsmemo.com/2010/11/house-dems-press-gop-to-abandon-their-federal-health-benefits.php?ref=fpa">events are overtaking</a> even <a href="http://infrequently.org/2009/09/a-contract-with-america/">my most sarcastic musings</a>. Too bad the Dems are doing this something like a year too late. They find their stones <em>now</em>? Oy.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/11/playing-catch-up/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>20 Things</title>
		<link>http://infrequently.org/2010/11/20-things/</link>
		<comments>http://infrequently.org/2010/11/20-things/#comments</comments>
		<pubDate>Thu, 18 Nov 2010 21:30:09 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1512</guid>
		<description><![CDATA[Big props to the team that put together the beautiful 20 Things web book. Browsers do a lot and most of it isn&#8217;t obvious. This and a more technical overview do a great job of spreading the word.]]></description>
			<content:encoded><![CDATA[<p>Big props to the team that put together the beautiful <a href="http://www.20thingsilearned.com/">20 Things</a> web book. Browsers do a lot and most of it isn&#8217;t obvious. This and <a href="http://taligarsiel.com/Projects/howbrowserswork1.htm">a more technical overview</a> do a great job of spreading the word.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/11/20-things/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Full Frontal JavaScript 2010</title>
		<link>http://infrequently.org/2010/11/full-frontal-javascript-2010/</link>
		<comments>http://infrequently.org/2010/11/full-frontal-javascript-2010/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 20:56:14 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1509</guid>
		<description><![CDATA[I&#8217;m getting ready to get on a plane this evening to speak at Full Frontal JavaScript 2010 in Brighton. I&#8217;ve been talking about something Chrome Frame-like since before I joined the project at Google, and the reasons I&#8217;m excited about it stretch way beyond liberation from the current set of boat-anchor browsers. Indeed, I think [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m getting ready to get on a plane this evening to speak at <a href="http://2010.full-frontal.org/schedule">Full Frontal JavaScript 2010</a> in Brighton. I&#8217;ve been talking about something Chrome Frame-like since before I joined the project at Google, and the reasons I&#8217;m excited about it stretch way beyond liberation from the current set of boat-anchor browsers. Indeed, I think what we&#8217;ve got in today&#8217;s best browsers isn&#8217;t even scratching the surface. Once the rate of change in the web platform gets back to where I think it should be, how we build things will change dramatically&#8230;and that&#8217;s change I&#8217;ve been waiting a decade for. Sure, today we can use libraries to get ourselves a competent version of what good browsers can do for you, but what will we be doing <em>next</em>? Remy Sharp is giving me a chance to paint that picture more fully in Brighton later this week and I&#8217;m incredibly grateful to him for the opportunity. I&#8217;ll post slides here after the talk, but if you&#8217;re in Brighton either for the conference or just &#8217;cause you&#8217;re awesome (you know who you are), I hope we&#8217;ll get to chat about it in person. The future&#8217;s about to get better.</p>
<p><b>Update</b>: slides are <a href="/10/ffjs/ffjs.html">here</a>. And no, they&#8217;re not supposed to make sense without the talk. Sorry.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/11/full-frontal-javascript-2010/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Anatomy Of A Hacker-News Story</title>
		<link>http://infrequently.org/2010/11/anatomy-of-a-hacker-news-story/</link>
		<comments>http://infrequently.org/2010/11/anatomy-of-a-hacker-news-story/#comments</comments>
		<pubDate>Sat, 06 Nov 2010 20:30:39 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1507</guid>
		<description><![CDATA[Hello, people I identify with (implicitly calling out the other), I have a theory you might identify with, since I think it describes you and your work and I identify with it. We will be ignoring counter-factuals today to make the process easier. Also, this post contains no actual data or research. It&#8217;s merely the [...]]]></description>
			<content:encoded><![CDATA[<p>Hello, people I identify with (implicitly calling out the other), I have a theory you might identify with, since I think it describes you and your work and I identify with it. We will be ignoring counter-factuals today to make the process easier. Also, this post contains no actual data or research. It&#8217;s merely the regurgitated musings of someone with very little experience in the topic at hand, armed with infinite amounts of self-congratulatory rightness. Because you and I already share attitudes and values, and because we&#8217;ve all read the same Paul Graham articles, this won&#8217;t be much of a debate.</p>
<p>Here&#8217;s my great theory:</p>
<h4>True statement, exaggerated</h4>
<p>Blah blah blah, setup, context, blah blah.</p>
<ul>
<li><b>Basic example:</b> drawing dubious (if implicit) causal connection. Gotcha!</li>
<li><b>Further example:</b> this one is more tenuous, but I think you&#8217;ll stick with it &#8217;cause you already swallowed the first one. Besides, you already agree with me.</li>
<li><b>Left-field example:</b> Phoning it in. Also, I&#8217;m on a horse.</li>
</ul>
<p><em>TODO(authorshandle): fill in with causal-sounding, non-research-backed explanations about why what I&#8217;m selling is true and not in any way exaggerated. If anything, it&#8217;s understated.</em></p>
<h4>Conclusion</h4>
<p>Disclaimer: this could be entirely wrong, so if it is (and we all know the odds), you read this disclaimer.</p>
<p>My startup is founded <em>entirely</em> around the principles I&#8217;ve outlined here, which is why we&#8217;re going to not only bring peace to the world, but get rich doing it. If you&#8217;re an investor, you&#8217;d be a sucker not to put your money with us. Not an investor? Please go click on the obviously placed link earlier in the paragraph and witness our closed beta signup form.</p>
<p><em>Self-aggrandizing &#8220;thanks&#8221; for help writing this article, preferably including name-drops of folks i think you&#8217;ve heard of, but not so many that it&#8217;s obvious.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/11/anatomy-of-a-hacker-news-story/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Hoisted From Comments Elsewhere</title>
		<link>http://infrequently.org/2010/11/hoisted-from-comments-elsewhere/</link>
		<comments>http://infrequently.org/2010/11/hoisted-from-comments-elsewhere/#comments</comments>
		<pubDate>Thu, 04 Nov 2010 18:38:22 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1505</guid>
		<description><![CDATA[Bart Bernhardt &#8212; Nerd Nite host, ad systems person you should really hire, and board game designer &#8212; on a thread regarding this paper: The New Godwin&#8217;s Law of Economic Analogies: As a stimulus argument grows longer, the probability of someone comparing government stimulus spending to ditch digging/filling approaches one.]]></description>
			<content:encoded><![CDATA[<p>Bart Bernhardt &#8212; <a href="http://www.linkedin.com/in/bartbernhardt">Nerd Nite host, ad systems person you should really hire, and board game designer</a> &#8212; on a thread regarding <a href="http://www.frbsf.org/publications/economics/papers/2010/wp10-17bk.pdf">this paper</a>:</p>
<blockquote><p>The New Godwin&#8217;s Law of Economic Analogies: As a stimulus argument grows longer, the probability of someone comparing government stimulus spending to ditch digging/filling approaches one.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/11/hoisted-from-comments-elsewhere/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

