<?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>Alex Russell on browsers, standards, and the process of progress.</description>
	<lastBuildDate>Thu, 16 May 2013 00:07:12 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Two Governments, Both Alike In Dignity</title>
		<link>http://infrequently.org/2013/04/two-governments-both-alike-in-dignity/</link>
		<comments>http://infrequently.org/2013/04/two-governments-both-alike-in-dignity/#comments</comments>
		<pubDate>Tue, 02 Apr 2013 15:41:17 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1997</guid>
		<description><![CDATA[Disclaimer: I&#8217;m engaged to Frances Berriman, the front-end lead at the UK&#8217;s Government Digital Service. She did not approve this post. It is, however, the product of many of our discussions. You&#8217;ll understand shortly why this is relevant. It seems entirely rational to be skeptical about governments doing things well. My personal life as a [...]]]></description>
				<content:encoded><![CDATA[<p><em>Disclaimer: I&#8217;m engaged to <a href="http://fberriman.com/">Frances Berriman</a>, the front-end lead at the UK&#8217;s Government Digital Service. She did not approve this post. It is, however, the product of many of our discussions. You&#8217;ll understand shortly why this is relevant.</em></p>
<p>It seems entirely rational to be skeptical about governments doing things well. My personal life as a migrant to the UK is mediated by heaving bureaucracies, lawyer-greased wheels, and stupefyingly arbitrary rules. Which is to say nothing of the plights of my friends and co-workers &#8212; Google engineers, mostly &#8212; whose migration stories to the US are horrifying in their idiocy. Both the US and UK seem beholden to big-stupid: instead of trying to attract and keep the best engineers, both countries seem hell-bent to keep them out. Heaven forbid they make things of value <em>here</em> (and pay taxes, contribute to society, etc.)! It takes no imagination whatsoever for me to conjure the banality and cruelty that are the predictable outcomes of inflexible, anachronistic, badly-formulated policy.</p>
<p>You see it perhaps most clearly when this banality is translated to purely transactional mediums. PDFs that you must fax &#8212; only to have a human re-type the results on the other end. Crazy use of phones (of course, only during business hours). Physical mail &#8212; the slowest and worst thing for a migrant like myself &#8212; might be the most humane form of the existing bureaucracy in the US. Your expectations are set at &#8220;paper&#8221;, and physical checks and &#8220;processing periods&#8221; measured in weeks feel somehow of a piece. It has always &#8220;worked&#8221; thus.</p>
<p>It&#8217;s befuddling then to have been a near witness to nothing short of the wholesale re-building of government services here in the UK to be easiest to navigate by these here newfangled computrons. And also just flat-out easy. The mantra is &#8220;digital by default&#8221;, and they seem to be <em>actually pulling it off</em>. Let me count the ways:</p>
<ol>
<li><a href="https://www.gov.uk/government/publications/directgov-2010-and-beyond-revolution-not-evolution-a-report-by-martha-lane-fox">High-level policy support for the effort</a>
</li>
<li>Working in the open. Does your government do its development <a href="https://github.com/alphagov/">on github?</a>
</li>
<li><a href="https://www.gov.uk/designprinciples">Designing services for the humans that use them</a>, not the ones who run them
</li>
<li>Making many processes that were either only-physical or damn infuriating near-trivial to do online
</li>
<li>Making key information <em>understandable</em>. Give the UK <a href="https://www.gov.uk/browse/business/limited-company" target="_new">&#8220;limited corporation&#8221; page</a> a view. Now compare to the <a href="https://www.ftb.ca.gov/businesses/bus_structures/LLCompany.shtml" target="_new">California version</a>. Day, meet night.
</li>
<li>Saving both government <em>and</em> citizens massive amounts of money in the process
</li>
</ol>
<p>They even have a <a href="https://www.gov.uk/government">progress bar</a> for how many of the ministries have been transformed in this way.</p>
<p>Over the same timeframe I&#8217;ve known a few of the good folks who have put themselves in the position of trying to effect changes like this at <a href="http://codeforamerica.org/">Code for America</a>. It&#8217;s anathema in the valley to say anything less than effusive about CFA &#8212; anything but how they&#8217;re doing such good, important work. How CFA has the potential to truly transform the way citizens and government interact. Etc, etc. And it&#8217;s all true. But while CFA has helped many in the US understand the idea that things <em>could</em> be better, the UK&#8217;s <a href="http://digital.cabinetoffice.gov.uk/">Government Digital Service</a> has gone out and <em>done it</em>.</p>
<p>So what separates them?</p>
<p>First, the sizes of the challenges need to be compared. The US has <a href="http://www.wolframalpha.com/input/?i=uk+vs.+us+population">5x the population</a>, an economy that&#8217;s 6x larger, and a federalist structure that makes fixing many problems more daunting than most UK citizens can possibly imagine. Next, it should be noted that London is a better place to try to hire the Right People (TM). Yes, it&#8217;s much more expensive to live here, but software salaries are also much lower (both in relative and absolute terms). There wasn&#8217;t as much tech going on here as in the valley to start with, and the gold-rush to produce shiny but less competent versions of existing websites for world+dog (aka: &#8220;the app ruse&#8221;) hasn&#8217;t created the engineering hiring frenzy here that it has stateside. There&#8217;s also a general distrust in the American psyche about the core proposition of the government doing good things. Public-spiritedness seems to so many of my generation a sort of dusty nostalgia that went the way of hemp and tie-dye. Close encounters with modern American government do little to repair the image.</p>
<p>But all of those seem surmountable. The US has more of everything, including the Right People (TM). Indeed, the UK is managing an entire first-world&#8217;s set of services on a smaller GDP. Why then do US public services, to be blunt, largely still suck?</p>
<p>The largest differences I&#8217;ve observed are about model. Instead of having a mandate to change things from the inside, the organizational clout to do it, and enough budget to make a big dent out of the gates (e.g. <a href="http://www.gov.uk">gov.uk</a>) <a href="http://codeforamerica.org/cities/apply-now/">CFA is in the painful position of needing to be invited</a> while at the same time trying to convince <a href="http://codeforamerica.org/fellows/apply/">talented and civic-minded engineers and designers to work for well below industry pay for a limited time on projects that don&#8217;t exist yet</a>.</p>
<p>Put yourselves in the shoes of a <a href="http://codeforamerica.org/2013-fellows/">CFA Fellow</a>: and your compatriots are meant to help change something important in the lives of citizens of a municipality that has &#8220;invited&#8221; you but which is under no real pressure to change, has likely moved no laws or contracts out of the way to prepare for your arrival, and they know you&#8217;re <a href="http://codeforamerica.org/fellowship-program-timeline/">short-timers</a>. Short-timers that <em>someone else is taking all the risk on and paying for</em>? What lasting change will you try to effect when you know that you&#8217;ve got a year (tops) and that whatever you deliver must be politically palatable to entrenched interests? And what about next year&#8217;s Fellows? What will they be handed to build on? What lasting bit of high-leverage infrastructure and service-design will they be contributing to?</p>
<p>The contrast between that and the uncomfortably-named &#8220;civil servants&#8221; of the GDS could not be more stark. I don&#8217;t get the sense that any of them think their job is a lifetime assignment &#8212; most assume they&#8217;ll be back at agencies any day now, and some of the early crop have already moved on in the way nerds tend to do &#8212; but at the pub they talk in terms of building for a generation, doing work that will last, and changing the entire ethos of the way services are produced and consumed. Doing more human work. And then they wake up the next morning and have the <em>authority and responsibility</em> to go do it.</p>
<p>I don&#8217;t want to be down on CFA. Indeed, it feels very much like the outside-government precursor to the GDS: <a href="http://www.mysociety.org/">mySociety</a>. mySociety was put together by many of the same public-spirited folks who initially built the Alpha of what would a year later become gov.uk and the GDS. Like CFA, mySociety spent years pleading from the outside, making wins where it could &#8212; and in the process refining ideas of what needed to change and how. But it was only once the model changed and they grabbed real leverage that they were able to make lasting change for the better. I fear CFA and the good, smart, hard-working people who are pouring their lives into it aren&#8217;t missing anything but leverage &#8212; and won&#8217;t make the sort of lasting change they want without it. CFA as an organization doesn&#8217;t seem to understand that&#8217;s the missing ingredient. America desperately needs for its public services to make the same sort of quantum leap that the UK&#8217;s are making now. It is such an important project, in fact, that it cannot be left to soft-golved, rose-tinted idealism. People&#8217;s lives are being made worse by mis-placed public spending, badly executed projects, and government services that seem to treat service as an afterthought. CFA <em>could</em> be changing this, and we owe it to ourselves and our friends there to ask clearly why that change hasn&#8217;t been forthcoming yet.</p>
<p>The CFA Fellows model has no large wins under its belt, no leverage, and no outward signs of introspection regarding its ability to deliver vs. the GDS model. Lets hope something larger is afoot beneath that placid surface.</p>
<p><b>Update:</b> I failed to mention in the first version of this post that the one of the largest philosophical differences between the two countries is the respective comfort levels with technocratic competence. There exists a strain of fatalism about government in the US that suggests that because government doesn&#8217;t often do things well, it shouldn&#8217;t try. It&#8217;s a distillation of the stunted worldviews of the libertarian and liberal-tarian elite and it pervades the valley. Of course governments that nobody expects anything of will deliver crappy service; how could it be otherwise?</p>
<p>What one witnesses here in the UK is the belief that regardless of what some theory says, it&#8217;s a problem when government does its job badly. To a lesser degree than I sense in years past, but still markedly moreso than in the US, the debate here isn&#8217;t about <em>can</em> the government get good at something, but <em>why isn&#8217;t it better at the things the people have given it responsibility for</em>?</p>
<p>As a result, the question quickly turns how one can expect a government to manage procurement of technical, intricate products for which it&#8217;s the only buyer (or supplier) without the competence to evaluate those products &#8212; let alone manage operations of them. Outsourcing&#8217;s proponents had their go here and enormous, open-ended, multi-year contracts yielded boondoggle after boondoggle. By putting contractors in a position of power over complexity, and starving the in-house experts of staffing and resources to match, the government forfeited it&#8217;s ability to change its own services to meet the needs of citizens. What changed with gov.uk was that the government decided that it <em>had to get good at the nuts and bolts of delivering the services</em>, outsourcing bits and pieces of small work, but owning the whole and managing it in-house. Having the Right People (TM) working on your team matters. If they&#8217;re at a contractor, they have a different responsibility and fiduciary duty. When the ownership of the product is mostly in-house, ambiguities borne of incomplete contract theory are settled in favor of the citizen (or worst case, government) interest, not the profit motive.</p>
<p>The gov.uk folks say &#8220;government should only do what only government can do&#8221;, but my observation has been that that&#8217;s not the end of the discussion: doing it well and doing it badly are still differentiable quantities. And doing better by citizens is <em>good</em>. Clearing space to do good is the essential challenge.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2013/04/two-governments-both-alike-in-dignity/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Layers of Confusion</title>
		<link>http://infrequently.org/2012/11/layers-of-confusion/</link>
		<comments>http://infrequently.org/2012/11/layers-of-confusion/#comments</comments>
		<pubDate>Fri, 23 Nov 2012 12:12:36 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1941</guid>
		<description><![CDATA[I missed a Plus post by Ian Hickson back from August but I saw it today through the magic of the twitters. It contains quite a lot to quibble about, but I want to home in on something he wrote in the comments in response to Will Sargent, RE: one of my posts on layering [...]]]></description>
				<content:encoded><![CDATA[<p>I missed a Plus post by <a href="https://plus.google.com/107429617152575897589/posts/SiLdNL9MsFw">Ian Hickson back from August</a> but I saw it today through the magic of the twitters. It contains quite a lot to quibble about, but I want to home in on something he wrote in the comments in response to <a href="https://plus.google.com/115037130211259860174/posts">Will Sargent</a>, RE: <a href="http://infrequently.org/2012/04/bedrock/">one of my posts on layering in the platform</a>:</p>
<blockquote><p>
&#8230;I don&#8217;t really share his vision. I think JS is an important part of the Web, but I don&#8217;t see it as any more core to the Web than CSS, HTML, the DOM APIs, HTTP, etc. Most of the proposals I&#8217;ve seen to take JS and build a platform on it tend to fall down on #3, #4, and #5. In particular, I think fundamentally #3 and #4 basically force the platform to have a declarative part (the declarative XAML part of .NET is how it managed to address #4, for instance, and the declarative design of XHTML2 and RDF are how they manage to address #3). That doesn&#8217;t have to mean that the code part is a secondary part, though. I think the Web has reached a point where you can think of the DOM as the core, with JS and the HTML syntax layered atop that (much like how in .NET there&#8217;s objects that can be represented in XAML or generated from C#), which puts the JS part on par with the HTML part in terms of importance to the platform.﻿
</p></blockquote>
<p>This is either me not articulating my &#8220;vision&#8221; clearly, Hixie mis-understanding my point(s), or some combination thereof. So I&#8217;ll try again in 4 paragraphs:</p>
<p>I make no claims about the relative importance of HTML, CSS, JS, DOM or any of the rest. It honestly feels silly to talk about the platform that way. I argue something very, very different: HTML, DOM, and (to a lesser extent) CSS <em>should</em> all conceptually bottom out at JS. I&#8217;m not saying &#8220;go write a browser in JS&#8221;&#8230;that&#8217;s also non-sequitur. JS  must, of course, appeal in turn to C/C++ so a &#8220;browser written in JS&#8221; would need privileged APIs provided by C/C++ or something lower level.</p>
<p>What I&#8217;m saying is something very direct: there&#8217;s no other ubiquitous programming language for the web. JS is the only game in town. As a result, when we describe imperative behavior in prose (as the HTML5 spec does) that behavior could, in theory, be implemented in JS (or some sub/super-set). Since HTML, DOM, and CSS aren&#8217;t Turing-complete, they naturally belong at a &#8220;higher level&#8221; in the web platform stack.</p>
<p>Now, all of this sounds dangerously academic and perhaps nuts&#8230;but consider that we have to expose APIs for nearly all of this stuff. Whenever we add something to HTML, CSS, etc., it always comes with some sort of API. Now, that could be a <em>good</em> API, or it could be an obtuse turn around the parser after some terrible string concatenation. </p>
<p>I&#8217;m claiming that you get better APIs when you design your imperative explanation of the declarative stuff &#8212; which you <em>MUST</em> do for specs to be sane &#8212; in JS. This means designing new APIs to help you accomplish the task at hand as you go. Doing it that way ends you up with the types, APIs, and security boundaries you&#8217;re going to need in the end anyway. Doing it the other way, patching crap onto the side later without explaining how the declarative stuff &#8220;works&#8221;, just leads to the pain and constant need for case-by-case revision that we see in today&#8217;s web APIs.</p>
<p>That&#8217;s the whole argument in 4 &#8216;grafs. It&#8217;s subtle, but I hope not terribly controversial. Importantly, nothing about it demands giving up on <em>any</em> of Hixie&#8217;s 5 arguments. He can keep &#8216;em all and still get a well-layered platform. We&#8217;ve got enough examples of doing it wrong under our belt to see how painful the badly-layered web is today. We can end this insanity &#8212; not by claiming that any part of the platform is &#8220;more important&#8221; &#8212; by explaining the platform in layers, higher levels in terms of the lower levels.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2012/11/layers-of-confusion/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Bits and Remainders</title>
		<link>http://infrequently.org/2012/11/bits-and-remainders/</link>
		<comments>http://infrequently.org/2012/11/bits-and-remainders/#comments</comments>
		<pubDate>Fri, 16 Nov 2012 18:13:03 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1934</guid>
		<description><![CDATA[I&#8217;ve been working on an epically-long blog post on the Offline problem for something like two months now and it&#8217;s still not done. That&#8217;s not so much to tease as warn you; Frances thinks I should post it in installments. It&#8217;s that long. Anyhow, as a result of that ever-growing design/analysis/writing hairball, I haven&#8217;t blogged [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been working on an epically-long blog post on the Offline problem for something like two months now and it&#8217;s still not done. That&#8217;s not so much to tease as warn you; <a href="http://fberriman.com/">Frances</a> thinks I should post it in installments. It&#8217;s that long.</p>
<p>Anyhow, as a result of that ever-growing design/analysis/writing hairball, I haven&#8217;t blogged when I might have. Notably, videos of some of my recent talks are now up, including my Fronteers closing talk:</p>
<p><iframe src="http://player.vimeo.com/video/53373706?badge=0" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
<p><a href="http://vimeo.com/53373706">Alex Russell | The Web Platform &#038; the Process of Progress | Fronteers 2012</a> from <a href="http://vimeo.com/fronteers">Fronteers</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>Special thanks to <a href="http://peter.sh/">Peter</a> and the Fronteers volunteers for managing to find a <a href="http://instagram.com/p/QZe3keOWcK/">pink <em>boozy</em> cake</a> (a culinary revelation!), simultaneously meeting my only (joke) demand as a speaker and trolling me in person. <em>WELL PLAYED</em>.</p>
<p>Also, give the rest of the <em>excellent</em> talks a <a href="http://vimeo.com/channels/fronteers12">gander over on Vimeo</a> . Personal favorites of mine include <a href="http://vimeo.com/channels/fronteers12/53317254">the ever-brillaint Phil Hawksworth</a>, <a href="http://vimeo.com/channels/fronteers12/53317253">Marcin Wichary&#8217;s stunning Doodles talk</a>, <a href="http://vimeo.com/channels/fronteers12/52882799">Lea Verou</a>, and <a href="http://vimeo.com/channels/fronteers12/53416986">Rebecca Murphey</a>&#8230;.actually, there were too many to list. Seriously, go check it out.</p>
<p>I also recently spoke at the London Ajax User&#8217;s Group, and video is <a href="http://skillsmatter.com/podcast/ajax-ria/the-future-of-the-web-platform">also available</a> (but not embeddable). Apologies for both videos including a lot of me rambling. I need to get better at this whole &#8220;public speaking&#8221; thing.</p>
<p>On a related note, <a href="http://2012.full-frontal.org/">FFJS was once again <em>brilliant</em></a>. Best one day conference going this side of the world, hands down. Congrats to Julie and Remy on a stonkingly good day.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2012/11/bits-and-remainders/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Please Vote</title>
		<link>http://infrequently.org/2012/05/please-vote/</link>
		<comments>http://infrequently.org/2012/05/please-vote/#comments</comments>
		<pubDate>Tue, 01 May 2012 11:30:40 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1864</guid>
		<description><![CDATA[If you&#8217;re a web developer, please vote in Paul Irish&#8217;s poll on browser support. The larger the population that votes, the more we can trust the answers, and the data is critical to making sense of how we collectively think about browser support. Go now. It won&#8217;t take long, I promise.]]></description>
				<content:encoded><![CDATA[<p>If you&#8217;re a web developer, please vote in <a href="http://gopollgo.com/what-browsers-do-you-test-your-sites-slash-apps-against">Paul Irish&#8217;s poll on browser support</a>. The larger the population that votes, the more we can trust the answers, and the data is critical to making sense of how we collectively think about browser support. Go now. It won&#8217;t take long, I promise.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2012/05/please-vote/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Overdue Credit Where It&#8217;s Due</title>
		<link>http://infrequently.org/2012/03/overdue-credit-where-its-due/</link>
		<comments>http://infrequently.org/2012/03/overdue-credit-where-its-due/#comments</comments>
		<pubDate>Mon, 05 Mar 2012 12:25:33 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1729</guid>
		<description><![CDATA[This is just the top of the backlog&#8230;there&#8217;s stuff still in my brain-bin from TPAC, but a couple of quick items worthy of a collective pip-pip!: MSFT Moves To More Aggressive IE Updates: Automatic updates work, and in conjunction with shorter development cycles they enable the process of progress to move faster. Kudos to MSFT [...]]]></description>
				<content:encoded><![CDATA[<p>This is just the top of the backlog&#8230;there&#8217;s stuff still in my brain-bin from TPAC, but a couple of quick items worthy of a collective pip-pip!:</p>
<ol>
<li><b><a href="http://www.zdnet.com/blog/bott/microsoft-to-begin-automatic-internet-explorer-upgrades-in-2012/4267">MSFT Moves To More Aggressive IE Updates</a>:</b> Automatic updates <em><a href="http://www.netmagazine.com/features/developers-guide-browser-adoption-rates">work</a></em>, and in conjunction with shorter development cycles they enable the process of progress to move faster. Kudos to MSFT and the IE team for taking a concrete step in the right direction.
</li>
<li><b><a href="http://news.cnet.com/8301-30685_3-57390399-264/jeff-jaffe-lights-a-fire-under-web-standardization/">Jeff Jaffe got the message</a></b> and, while continuing to say tone-deaf things like &#8220;the W3C is a volunteer organization&#8221;, thereby ignoring the cause of the prefix squatter&#8217;s discontent from the perspective of standards &#8212; that there is a good faith way to act and that Apple has run afoul of it by not plumping specs for their features, and that those shipping common code have been burned by unwittingly shipping features which have been found to undermine the good faith of the process &#8212; at least he has said that speeding up the process is a key item for action this year at the W3C. It&#8217;s not much, but it deserves to be noted as a refreshing bit of honest self assesment.
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2012/03/overdue-credit-where-its-due/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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"><table><tr><td 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: #FF0000;">export</span> <span style="color: #FF0000;">class</span> DropDownButton <span style="color: #FF0000;">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: #FF0000;">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></td></tr></table></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"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> widgets <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; 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: #000066; 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: #000066; font-weight: bold;">prototype</span> <span style="color: #339933;">=</span> <span style="">Object</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>Widget.<span style="color: #000066; font-weight: bold;">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: #000066; 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: #000066; 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></td></tr></table></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"><table><tr><td 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: #000066; 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></td></tr></table></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"><table><tr><td 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></td></tr></table></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"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #000066; 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: #000066; 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: #000066; 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: #000066; 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: #000066; 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: #006600; 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: #000066; 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: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>name<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>name<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>name<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>name<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>name<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: #000066; 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: #000066; 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: #006600; 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: #000066; 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: #006600; 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: #000066; 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: #006600; 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: #000066; 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: #006600; 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: #000066; 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: #006600; 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></td></tr></table></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>
	</channel>
</rss>
