<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en"><title type="text">igvita.com</title><link rel="alternate" type="text/html" href="http://www.igvita.com" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.igvita.com/igvita" /><subtitle type="text">a goal is a dream with a deadline</subtitle><author><name>Ilya Grigorik</name><email>ilya@igvita.com</email><uri>http://www.igvita.com/</uri></author><updated>2012-02-03T05:43:04+00:00</updated><feedburner:info uri="igvita" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><id>http://www.igvita.com/</id><geo:lat>37.40679</geo:lat><geo:long>-122.074613</geo:long><entry><title type="html">Building a Modern Web Stack for the Real-time Web</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/OT97_wi8hwc/" /><updated>2012-01-18T00:00:00-08:00</updated><id>http://www.igvita.com/2012/01/18/building-a-modern-web-stack-for-the-realtime-web/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/web-construction.png' class='left' /&gt;The web is evolving. After a few years of iteration the WebSockets spec is finally here (&lt;a href="http://tools.ietf.org/html/rfc6455"&gt;RFC 6455&lt;/a&gt;), and as of late 2011 both Chrome and Firefox are &lt;a href="http://www.igvita.com/2011/12/01/web-vpn-secure-proxies-with-spdy-chrome/"&gt;SPDY capable&lt;/a&gt;. These additions are much more than just "enhancing AJAX", as we now have true real-time communication in the browser: stream multiplexing, flow control, framing, and significant latency and performance improvements. &lt;strong&gt;Now, we just need to drag our "back office" - our web frontends, app servers, and everything in between into this century to enable us to take advantage of these new capabilities.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;We're optimized for "Yesterday's Web"&lt;/h2&gt;

&lt;p&gt;Modern backend architecture should allow you to terminate the user connection as close to the user as possible to minimize latency - this is your load balancer or web server occupying ports &lt;code&gt;80&lt;/code&gt; and &lt;code&gt;443 (SSL)&lt;/code&gt;. From there, the request is routed on the internal network from the frontend to the backend service, which will generate the response. Unfortunately, the current state of our "back office" routing is not only outdated, but often is also the limiting factor in our adoption of these real-time protocols.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/ws-spdy.png' class='left' /&gt;&lt;a href="http://www.igvita.com/2009/12/22/ruby-websockets-tcp-for-the-browser/"&gt;WebSockets&lt;/a&gt; and &lt;a href="http://www.igvita.com/2011/04/07/life-beyond-http-11-googles-spdy/"&gt;SPDY&lt;/a&gt; are both &lt;a href="http://en.wikipedia.org/wiki/Multiplexing"&gt;multiplexed protocols&lt;/a&gt; which are optimized to carry multiple, interleaved streams of data over the same TCP pipe. Unfortunately, popular choices such as Apache and Nginx have no understanding of this and at best &lt;a href="https://github.com/yaoweibin/nginx_tcp_proxy_module"&gt;degrade&lt;/a&gt; to dumb "TCP proxies". Even worse, since they do not understand multiplexing, stream flow-control and priority handling goes out the door as well. Finally, both WebSockets and SPDY communicate in &lt;a href="http://www.igvita.com/2011/04/07/life-beyond-http-11-googles-spdy/"&gt;framed messages&lt;/a&gt;, not in TCP streams, which need to be re-parsed at each stage.&lt;/p&gt;

&lt;p&gt;Put all of this together and you quickly realize why your own back office web stack, and even the popular platforms such as Heroku and Google's App Engine are unable to provide WebSockets or SPDY support: &lt;strong&gt;our services are fronted by servers and software which was designed for yesterday's web.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Architecture for the "Real-time Web"&lt;/h2&gt;

&lt;p&gt;HTTP is not going away anytime soon, and we will have to support both the old and the new protocols for some time to come. One attempt at this has been the &lt;kbd&gt;SPDY &gt; HTTP&lt;/kbd&gt; proxy, which converts a multiplexed stream into a series of old-fashioned HTTP requests. This works, and it allows us to reuse our old infrastructure, but this is &lt;strong&gt;exactly backwards&lt;/strong&gt; from what we need to be doing!&lt;/p&gt;

&lt;p&gt;Instead of converting an optimized, multiplexed stream into a series of internal HTTP dispatches, we should be asking for &lt;kbd&gt;HTTP &gt; SPDY&lt;/kbd&gt; infrastructure, which would allow us to move beyond our outmoded architectures. In 2012, we should demand our internal infrastructure to offer the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request and Response &lt;strong&gt;streaming should be the default&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Connections to backend servers should be &lt;strong&gt;persistent&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Communication with backend servers should be &lt;strong&gt;message-oriented&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Communication between clients and backends should be &lt;strong&gt;bi-directional&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Make SPDY the default, embrace dynamic topologies&lt;/h2&gt;

&lt;p&gt;The first step towards these goals is to recognize that translating SPDY to HTTP is a convenient path in the short term, but exactly the wrong path in the long term. SPDY offers multiplexing, flow control, optimized compression, and framing. We should embrace it and make it the default on the backend. Once we have a multiplexed, message-oriented protocol on the backend, we can also finally stop reparsing the same TCP stream on every server. &lt;em&gt;Writing HTTP parsers in 2012 is neither fun nor an interesting problem.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/dynamic-routing.png' class='left' /&gt;Finally, this architecture should not require a dedicated OPS team, or a custom software platform to maintain. Modern web applications are rarely powered by a single host and require dynamic (re)configuration and management. Services such as Heroku, CloudFoundry, and GAE have built their own "routing fabrics" to handle these problems. Instead, we need to design architectures where the frontends and the backends are &lt;a href="https://github.com/igrigorik/zeroconf-router"&gt;decoupled by default&lt;/a&gt; and require minimal intervention and maintenance.&lt;/p&gt;

&lt;h2&gt;Adopt a modern Session Layer&lt;/h2&gt;

&lt;p&gt;Building dynamic network typologies is not for the faint of heart, especially once we add the additional requirements for message-oriented communication, multiplexed streams and a grab bag of performance constraints. Thankfully, libraries such as &lt;a href="http://www.zeromq.org/"&gt;ØMQ&lt;/a&gt; offer all of the above and more, all wrapped behind a &lt;a href="http://www.igvita.com/2010/09/03/zeromq-modern-fast-networking-stack/"&gt;simple and an intuitive API&lt;/a&gt;. Let the frontend parse and emit SPDY frames, and then route them internally as ØMQ messages to any number of subscribers.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/zeromq-router.png' class='left' /&gt; &lt;a href="http://mongrel2.org/"&gt;Mongrel2&lt;/a&gt; was one of the first web servers to explore this type of architecture with ØMQ, which allowed it to sidestep the entire problem of backend configuration, as well as enable a number of interesting worker topology patterns. There is still room for improvement, but it is a much needed step in the right direction. As a concrete example, let's consider a sample workflow with SPDY and ØMQ:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An HTTP (or SPDY) request arrives to the frontend&lt;/li&gt;
&lt;li&gt;Frontend parses the request and generates &lt;code&gt;SYN_STREAM&lt;/code&gt;, &lt;code&gt;HEADERS&lt;/code&gt; and &lt;code&gt;DATA&lt;/code&gt; SPDY frames&lt;/li&gt;
&lt;li&gt;The messages are delivered into a &lt;code&gt;PUSH&lt;/code&gt; ØMQ socket (ala Mongrel2)&lt;/li&gt;
&lt;li&gt;Backend subscribers use a &lt;code&gt;PULL&lt;/code&gt; socket to process the SPDY stream&lt;/li&gt;
&lt;li&gt;Backend subscriber streams a response back to the frontend&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The communication is done over a persistent channel with message-oriented semantics, the frontend and the backends are completely decoupled, and we can finally stop punching "TCP holes" in our networks to support the modern web.&lt;/p&gt;

&lt;h2&gt;Supporting HTTP 2.0 in the back office&lt;/h2&gt;

&lt;p&gt;The new protocols are here, but the supporting "back office" architecture requires a serious update: &lt;strong&gt;SSL is becoming the default, streaming is no longer an option, and long-lived persistent connections are in.&lt;/strong&gt; SPDY is gaining momentum, and I have no doubts that in the not so distant future it will be an IETF approved protocol. Similarly, ØMQ is not the only alternative for internal routing, but it is definitely one that has been gaining momentum.&lt;/p&gt;

&lt;p&gt;Fast HTTP parsing and routing is simply not enough to support the modern web use cases. Likewise, punching "TCP holes" in our infrastructure is not a viable long-term solution - in 2012 we should be asking for more. Yes, I'm looking at you Varnish, Nginx, Apache and friends.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=OT97_wi8hwc:Pp7Q4OIBlco:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/OT97_wi8hwc" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2012/01/18/building-a-modern-web-stack-for-the-realtime-web/</feedburner:origLink></entry><entry><title type="html">Google Web Toolkit: GWT, Closure, NaCl, Dart &amp; JS</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/1zMQ1_Sa3ho/" /><updated>2012-01-05T00:00:00-08:00</updated><id>http://www.igvita.com/2012/01/05/google-web-toolkit-gwt-closure-nacl-dart-js/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/google-toolkit-small.png' class='left' /&gt; As web developers, one thing we're not short on is the number of options when it comes to web frameworks, languages and runtimes. Google alone is now officially supporting at least five different platforms: JavaScript, &lt;a href="http://code.google.com/webtoolkit/"&gt;GWT&lt;/a&gt;, &lt;a href="http://code.google.com/closure/"&gt;Closure&lt;/a&gt;, and the two recent additions in &lt;a href="https://developers.google.com/native-client/"&gt;NaCl&lt;/a&gt; and &lt;a href="http://www.dartlang.org/"&gt;Dart&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On one hand, it is easy to look at this list and wonder why all the dissonance and competition. After all, all of these teams are within the same company, can't they just agree to work together? However, if you look at the full scope of these projects, a slightly more interesting perspective emerges: &lt;strong&gt;it is not about trying to find the "one true way" to build a modern web application, instead, intentionally or not, Google is funding and providing the tools for every take at the problem.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;The "Google Web Toolkit"&lt;/h2&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/google-web-toolkit.png' class='center' /&gt;&lt;/p&gt;

&lt;p&gt;Regardless of the technology, the end result, at the center of the diagram, is the plain old HTML page, which is executed by the browser. Both of these technologies is something that Google has put a lot of investment in: heavy involvement with HTML5, and of course the Chrome browser itself.&lt;/p&gt;

&lt;p&gt;However, most web apps today are not just static HTML, to add interactivity we have historically relied on JavaScript, which is where the Chrome V8 runtime comes in with its focus on speed. "&lt;a href="http://www.youtube.com/watch?v=nCgQDjiotG0"&gt;Fast is a feature&lt;/a&gt;", especially when you have apps like GMail which consist of &lt;a href="http://www.infoworld.com/d/developer-world/google-executive-frustrated-java-c-complexity-375"&gt;443,000+ lines of handrolled JavaScript&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Developing in raw JavaScript can be fun, but the lack of tooling can be a problem at scale. &lt;a href="http://code.google.com/closure/"&gt;Closure&lt;/a&gt; is one attempt at solving this problem by introducing a dedicated linter/compiler, which also adds features like namespaces, type checking, data hiding, a "standard library", and a number of other extensions. In effect, you write Closure flavored JavaScript, you pass it &lt;a href="http://code.google.com/closure/compiler/docs/gettingstarted_app.html"&gt;through the compiler&lt;/a&gt;, and the output is optimized and minified JavaScript. The Google+ team has professed their love for Closure on &lt;a href="https://plus.google.com/113127438179392830442/posts/48n5wxsCSga"&gt;numerous occasions&lt;/a&gt;, and they are just one of the many teams within Google using it in production.&lt;/p&gt;

&lt;h2&gt;Structured Web Programming with GWT &amp;amp; Dart&lt;/h2&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/gwt-logo.png' class='left' /&gt; But, you say, I love the Eclipse toolchain, Java and all the infrastructure that comes with it - if only we could use that to build our web applications! That's &lt;a href="http://code.google.com/webtoolkit/"&gt;Google Web Toolkit&lt;/a&gt; (GWT). The GWT SDK allows you to write your entire application in Java and then compile the source into optimized JavaScript. In fact, that's exactly how Google AdSense is built. And for a more "entertaining" example, add a framework like &lt;a href="http://code.google.com/p/playn/"&gt;PlayN&lt;/a&gt; on top of GWT, and you get &lt;a href="http://youtu.be/F_sbusEUz5w?t=39s"&gt;AngryBirds in the browser&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;However, not everyone is a fan of Java. What if we had a language optimized for "structured web programming"? Say hello to &lt;a href="http://www.dartlang.org/"&gt;Dart&lt;/a&gt;. The language is still in technology preview, but the goal is to take a comprehensive approach at the problem: structured, &lt;a href="http://www.youtube.com/watch?v=UZOIAz-eR34"&gt;familiar language&lt;/a&gt;, common libraries, modularity, and built-in tool support. Boot up your Dart editor (Eclipse based), develop and debug your app, and the Dart compiler will emit optimized JavaScript when you ship the product.&lt;/p&gt;

&lt;h2&gt;Life beyond JavaScript&lt;/h2&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/12/dart-logo.png' class='left' /&gt; Wherever there is a browser, there is a JavaScript engine. This makes JavaScript an incredibly powerful target. However, why should we pin the future of the web on JavaScript alone?&lt;/p&gt;

&lt;p&gt;Dart, in addition to compiling to JavaScript also offers the &lt;em&gt;"Dart VM"&lt;/em&gt;, which will execute the code directly on your local workstation or server. In fact, you can even download and build &lt;a href="http://code.google.com/p/dart/wiki/BuildingDartium"&gt;Dartium&lt;/a&gt;, which is a Chromium build with a built-in Dart VM - no JavaScript required!&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;application/dart&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;HTMLElement&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Hello from Dart&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;But if we can have Dart running natively in browser, what about all the other languages? That's &lt;a href="https://developers.google.com/native-client/"&gt;Native Client&lt;/a&gt; (NaCl), which allows you to run native compiled code directly in your browser! Grab your C/C++ source, compile it with the &lt;a href="https://developers.google.com/native-client/overview#how-nacl-works"&gt;NaCl toolchain&lt;/a&gt;, and you can have your physics engine, game, or any other &lt;a href="http://youtu.be/g3aBfkFbPWk?t=24m58s"&gt;CPU intensive app&lt;/a&gt; run directly in the browser.&lt;/p&gt;

&lt;p&gt;Additionally, there is ongoing work on &lt;a href="http://nativeclient.googlecode.com/svn/data/site/pnacl.pdf"&gt;Portable NaCl&lt;/a&gt; (PNaCl), which will accept any LLVM bytecode and run it in NaCL - which, in turn, means that we can run Python, Ruby, Lua, and dozens of other languages right in the browser. For the curious, see my RubyConf 2011 talk on this subject below (&lt;a href="http://www.slideshare.net/igrigorik/ruby-in-the-browser-rubyconf-2011"&gt;slides&lt;/a&gt;):&lt;/p&gt;

&lt;p align="center"&gt;
&lt;iframe width="640" height="360" src="http://www.youtube.com/embed/k07aKM0QTyA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;


&lt;h2&gt;The Google Coopetition&lt;/h2&gt;

&lt;p&gt;It is easy to look at all the alternatives and wonder, what does Dart mean for GWT, or Closure, how does NaCl affect the picture, and what about the good old JavaScript itself? &lt;strong&gt;What's the "one true way" to build a modern web app in 2012? The short answer is: wrong question, the answer depends on your context.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google itself has many high profile products powered by each option above, and each has its strengths and weaknesses, as well as an audience for which it is the &lt;em&gt;"right fit"&lt;/em&gt;. Instead of trying to bet on any single solution Google is systematically investing into each and every alternative route - call it cooperative competition.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=1zMQ1_Sa3ho:-sAKDxqtEFI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/1zMQ1_Sa3ho" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2012/01/05/google-web-toolkit-gwt-closure-nacl-dart-js/</feedburner:origLink></entry><entry><title type="html">Don't "Push" Your Pull Requests</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/OyINjX-8fmU/" /><updated>2011-12-19T00:00:00-08:00</updated><id>http://www.igvita.com/2011/12/19/dont-push-your-pull-requests/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/oss-dev.jpg' class='left' /&gt;You've run into a problem, or you have an itch to scratch, so you fire up the editor and dive right in. On a good occasion the patch is simple, so you pat yourself on the back, fire off a pull request and sit back and watch - even though it is a simple patch, past experience shows that often you will have to incorporate some feedback before it will be merged upstream.&lt;/p&gt;

&lt;p&gt;Then, every once in a while, you stumble on that gnarly problem - the one that looked simple on the surface - and you spend the better part of your day on it, or more, and the further you get in, the more committed you become to see it through. Finally, you emerge victorious with a 300+ line patch, a dozen modified files, and a feeling that you have just done the world a favor - &lt;strong&gt;time to fire off the pull request!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where it all breaks down. You expect gratitude for all the time, work, and effort you've put in, but the maintainer looks in horror at the patch as he tries to enumerate all the reasons why he can't accept it. Half the time, he doesn't even know where to start, so he picks a nitpick and digs in - &lt;strong&gt;your contribution is going nowhere fast and neither side is to blame.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Don't "push" the pull request&lt;/h2&gt;

&lt;p&gt;Contributions are always welcome, but surprise patches are mostly just a burden. Yes, you are offering your help, but someone else will have to maintain your code over the long term - get their buy-in first, avoid surprises. Even worse, a localized change to address a specific problem will often miss the full implications to the project: other existing use cases, future roadmap plans, or overall architectural decisions. A good idea can be implemented inappropriately for the specific project; it can be invalidated by another effort that you may not even be aware of; the timing may be wrong, and a dozen other reasons can conspire against you.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/oss-fan.png' class='left' /&gt;Those responsible for maintaining the code have the best perspective, so engage them early. That is not to say they are always right, and you may have to make  your case regardless, but this is a discussion better had before you write the code, not after. This is one of the most frustrating paradoxes in open-source: all too often it is your most engaged fans that fall into this trap, spending their nights and weekends working on a massive contribution, only to be disappointed when the maintainer flat out rejects their work.&lt;/p&gt;

&lt;h2&gt;Code reviews are hard: start early&lt;/h2&gt;

&lt;p&gt;Next time, before you dive into the editor, open a discussion, outline your problem and solution and offer to do the work. It shouldn't take more than a paragraph to explain the goal - if you need an essay, that's a sign already that you need to break it up, or the problem is not yet well defined. If the project or the change is large, pick a specific reviewer and go over the design. &lt;strong&gt;Ask for help and input early, and magically, you will find your code getting "pulled" (merged) on schedule.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Code reviews are hard. In fact, as it turns out, the &lt;a href="http://smartbear.com/resources/cc/11_Best_Practices_for_Peer_Code_Review.pdf"&gt;effectiveness of a code-review drops dramatically&lt;/a&gt; after 200-400 lines of code, and the suggested inspection rate is at most 300-500 lines an hour. Keep this in mind, break down large commits into small, manageable chunks. As a rule of thumb, shoot for half an hour of review, or less than 200 lines with good and clear (not clever) code. If there are multiple commits, then provide a roadmap, and get feedback on each piece as it comes together.&lt;/p&gt;

&lt;h2&gt;Good work gets "pulled" not "pushed"&lt;/h2&gt;

&lt;p&gt;There is nothing more frustrating than to read the threads, or even worse, be on the receiving end of this experience gone wrong. The contributor is wounded because they are not recognized, and the maintainer is caught in a dilemma: they want to build and foster their community, but they have to dig-in against their biggest fans. There is no winner here and neither side is to blame.&lt;/p&gt;

&lt;p&gt;Next time, before you dive into the editor, open a discussion, outline your problem and solution, and offer to do the work - don't "push" the pull request, and don't work in the dark.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=OyINjX-8fmU:8ugJqRGJLFo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/OyINjX-8fmU" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/12/19/dont-push-your-pull-requests/</feedburner:origLink></entry><entry><title type="html">Web-VPN: Secure Proxies with SPDY &amp; Chrome</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/qMX7QrXbIKw/" /><updated>2011-12-01T00:00:00-08:00</updated><id>http://www.igvita.com/2011/12/01/web-vpn-secure-proxies-with-spdy-chrome/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/kindle-fire.png' class='left' /&gt;Amazon's recent launch of their new Kindle Fire device delivered an interesting surprise: their &lt;a href="http://amazonsilk.wordpress.com/2011/09/28/introducing-amazon-silk/"&gt;Silk browser&lt;/a&gt; routes all requests via an Amazon powered SPDY proxy! In principle, this is not new; Opera, Blackberry and many other mobile providers have been using similar approaches to "optimize" the browsing experience for some time. However, Silk's announcement immediately generated a &lt;a href="http://www.eweek.com/c/a/Security/Amazon-Assures-Congress-It-Guards-User-Privacy-on-Silk-Browser-Kindle-Fire-634639/"&gt;slew&lt;/a&gt; of &lt;a href="http://nakedsecurity.sophos.com/2011/09/28/amazon-kindle-fires-silk-browser-sounds-privacy-alarm-bells/"&gt;security outcries&lt;/a&gt;: doesn't this mean that Amazon is now effectively a &lt;a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack"&gt;man in the middle&lt;/a&gt; (MITM) for all of our sessions, including SSL? Is this all just a big data mining ploy, or worse?&lt;/p&gt;

&lt;p&gt;Turns out, the answer is: none of the above. Amazon does not route SSL traffic through their SPDY proxies, instead all &lt;a href="https://www.eff.org/2011/october/amazon-fire%E2%80%99s-new-browser-puts-spotlight-privacy-trade-offs"&gt;HTTPS requests are routed directly&lt;/a&gt; to the destination. However, this incident did surface an interesting underlying question: &lt;strong&gt;is it, in fact, possible for a web browser to securely route SSL sessions via a web-proxy?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Tunneling SSL over HTTP&lt;/h2&gt;

&lt;p&gt;First, it is worth recalling that HTTP does allow us to &lt;a href="http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01#section-3.3"&gt;tunnel SSL connections&lt;/a&gt;, end-to-end, via an HTTP proxy. This is a little known protocol feature, but an important one for our purposes:&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/connect-proxy.png' class='center' /&gt;&lt;/p&gt;

&lt;p&gt;To proxy an HTTPS session the client connects to the proxy by sending a special &lt;code&gt;CONNECT&lt;/code&gt; HTTP method, which also includes just the host and the port of the destination. The proxy authenticates the request, completes the TCP handshake with the specified destination and returns a &lt;code&gt;200 Connection Established&lt;/code&gt; response, after which, it simply becomes a dumb, two-way router. At this point, the client and the server negotiate the SSL session and start to exchange encrypted data directly through the proxy. In other words, the proxy only sees encrypted data, and the only thing it knows are the hostnames and the ports of both parties.&lt;/p&gt;

&lt;p&gt;This is great, but there is still one problem: the original &lt;code&gt;CONNECT&lt;/code&gt; handshake (in green), alongside the host and the port of the destination is sent in clear text. Even worse, the proxy authentication (if any) is also running over the same insecure channel. &lt;strong&gt;Unfortunately, browsers today do not support secure HTTP proxies!&lt;/strong&gt; Hence the reason why we've historically resorted to heavyweight SSL VPN's, SOCKS tunnels, and the like.&lt;/p&gt;

&lt;h2&gt;Chrome, SPDY and Secure Web Proxies&lt;/h2&gt;

&lt;p&gt;Except, as it turns out, what we said above is not entirely true: earlier this year, Google Chrome added support for secure web proxies! Since all SPDY sessions run over SSL, a SPDY proxy, by definition, would need to be SSL capable. Hence, the Chrome team went ahead and &lt;a href="http://dev.chromium.org/developers/design-documents/secure-web-proxy"&gt;added secure web proxy support&lt;/a&gt; - nice.&lt;/p&gt;

&lt;blockquote&gt;Browsers today do not support secure proxies. Although proxies can tunnel SSL, connectivity to the proxy itself is only over HTTP. To support SPDY, we need to modify Chromium to support a SSL-based proxy.&lt;/blockquote&gt;


&lt;h2&gt;Web-VPN &amp;amp; Chrome&lt;/h2&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/web-vpn.png' class='left' /&gt; Enabling SSL for the first hop to the proxy seems like a minor change - and it did go largely unnoticed - but it opens up some really interesting use cases! For one, the authentication can now be handled at a certificate level, which can be provisioned, revoked, and verified securely. In other words, your Chrome browser is now also a "&lt;a href="https://groups.google.com/forum/#!msg/spdy-dev/Is85w_H1510/UeVa3AOsoiQJ"&gt;Web-VPN client&lt;/a&gt;" - except without the annoying installation, configuration, and maintenance!&lt;/p&gt;

&lt;p&gt;How exactly would Web-VPN work? Simply deploy a &lt;a href="http://www.chromium.org/spdy/spdy-proxy"&gt;secure HTTP proxy&lt;/a&gt; as a gateway to any private network, point your Chrome browser at it, and voila, you will be able to resolve any internal hostname or service just as if you were running a VPN client. The first hop to the proxy runs over SSL, and all subsequent tunnels as well.&lt;/p&gt;

&lt;h2&gt;SPDY: 2012 is the year!&lt;/h2&gt;

&lt;p&gt;One of the primary motivations for &lt;a href="http://www.chromium.org/spdy"&gt;SPDY&lt;/a&gt; is to reduce the overall &lt;a href="http://www.igvita.com/2011/04/07/life-beyond-http-11-googles-spdy"&gt;page loading time&lt;/a&gt;. However, while speed is important, the security aspects are arguably even more critical - support for secure web proxies is one of many great examples.&lt;/p&gt;

&lt;p&gt;Interestingly, Chrome is on track to take the &lt;a href="http://gs.statcounter.com/"&gt;#2 browser spot&lt;/a&gt; away from Firefox before the end of the year, and at the same time, Firefox 11 will arrive on December 20th. So what? Well, one of the less often mentioned features of Firefox 11 is the built-in SPDY support! Combined, between Chrome and Firefox, this means that &lt;strong&gt;over 50% of all internet sessions will be SPDY capable. Mark 2012 as the beginning of the end for HTTP.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=qMX7QrXbIKw:lz0vfXMKPpQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/qMX7QrXbIKw" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/12/01/web-vpn-secure-proxies-with-spdy-chrome/</feedburner:origLink></entry><entry><title type="html">Faster Web vs. TCP Slow-Start</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/mbCbT_DPQWI/" /><updated>2011-10-20T00:00:00-07:00</updated><id>http://www.igvita.com/2011/10/20/faster-web-vs-tcp-slow-start/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/isp.png' class='left' /&gt;Ever obsess about trying to find the "best and fastest" internet provider? Having recently gone through the marketing vortex of comparing a dozen different plans, I was then reminded of a simple fact: the primary metric (bandwidth) used by the industry  is actually highly misleading. It turns out, &lt;strong&gt;for most web-browsing use cases, an internet connection over several Mbps offers but a tiny improvement in performance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One of the main culprits is "TCP slow-start", and yes that is a feature, not a bug. To understand why, we have to look inside of the TCP stack itself, and in doing so we can also learn a few interesting tips for how to build faster web-services in general.&lt;/p&gt;

&lt;h2&gt;TCP Slow-start&lt;/h2&gt;

&lt;p&gt;TCP offers a dozen different built-in features, but the two we are interested in are &lt;a href="http://tools.ietf.org/html/rfc5681"&gt;congestion control&lt;/a&gt; and &lt;a href="http://tools.ietf.org/html/rfc5681#section-3.1"&gt;congestion avoidance&lt;/a&gt;. TCP slow-start specifically is an implementation of congestion control within the TCP layer:&lt;/p&gt;

&lt;blockquote cite="http://en.wikipedia.org/wiki/Slow-start"&gt;Slow start is used in conjunction with other algorithms to avoid sending more data than the network is capable of transmitting, that is, to avoid causing network congestion.&lt;/blockquote&gt;


&lt;p&gt;&lt;a href="http://www.stevesouders.com/blog/2010/07/13/velocity-tcp-and-the-lower-bound-of-web-performance/"&gt;&lt;img src='http://www.igvita.com/posts/11/cwnd.png' class='left' /&gt;&lt;/a&gt; The high-level flow is simple: the client sends a SYN packet which advertises its maximum buffer size (&lt;em&gt;rwnd&lt;/em&gt; - receive window), the sender replies by sending several packets back (&lt;em&gt;cwnd&lt;/em&gt; - congestion window) and then each time it receives an ACK from the client, it doubles the number of packets that can be "on the wire" while unacknowledged.&lt;/p&gt;

&lt;p&gt;This phase is also known as the "exponential growth" phase of the TCP connection. OSI school has an an excellent animation illustrating this phase: &lt;a href="http://www.osischool.com/protocol/Tcp/slidingWindow/index.php"&gt;scroll to the bottom and hit play&lt;/a&gt;.So, why do we care? Well, no matter what the size of your pipe,  &lt;strong&gt;every TCP connection goes through this phase, which also means that more often than not, the utilized bandwidth is effectively limited by the settings of the sender's and receiver's buffer sizes&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;HTTP and TCP slow start&lt;/h2&gt;

&lt;p&gt;Of course, a higher bandwidth connection will help when you are streaming a large file, or running a vanity speed test. The problem is, HTTP traffic tends to make use of short and bursty connections - in these cases we often never even reach the full capacity of our pipes! &lt;a href="http://docs.google.com/a/chromium.org/viewer?a=v&amp;amp;pid=sites&amp;amp;srcid=Y2hyb21pdW0ub3JnfGRldnxneDoxMzcyOWI1N2I4YzI3NzE2"&gt;Research done at Google&lt;/a&gt; shows that an increase from 5Mbps to 10Mbps results in a disappointing 5% improvement in page load times.&lt;/p&gt;

&lt;p&gt;Or put slightly differently, &lt;strong&gt;a 10Mbps connection, on average uses only 16% of its capacity. Yikes!&lt;/strong&gt; As it turns out, if we want faster internet, we should focus on cutting down the round-trip time between the client and server, not necessarily just investing in bigger pipes.&lt;/p&gt;

&lt;h2&gt;The story of CWND&lt;/h2&gt;

&lt;p&gt;If TCP slow start is, well, slow, then couldn't we just make it faster? Turns out, until very recently the Linux TCP stack itself was &lt;a href="http://kerneltrap.org/mailarchive/linux-netdev/2009/10/26/6258693"&gt;hardcoded&lt;/a&gt; to start with the congestion window (cwnd) of just 3 or 4 packets, which amounts to about 4kb (~1360 bytes per packet). Combine that with the unfortunately frequent &lt;a href="http://www.igvita.com/2011/10/04/optimizing-http-keep-alive-and-pipelining/"&gt;pathological case of fetching a single resource per connection&lt;/a&gt;, and you have managed to severely limit your performance.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/speed-bandwidth.png' class='left' /&gt; As of kernel version 2.6.33, following a protracted discussion and a &lt;a href="http://tools.ietf.org/html/draft-allman-tcpm-bump-initcwnd-00"&gt;number&lt;/a&gt; of &lt;a href="http://tools.ietf.org/html/draft-ietf-tcpm-initcwnd-00"&gt;IETF recommendations&lt;/a&gt;, the initial cwnd value has been reset to 10 packets, which in itself is a huge step forward. Only one problem, guess what kernel versions most servers run today? Yes, perhaps it is time to upgrade your servers.As a practical tip, if you have been thinking about &lt;a href="http://www.igvita.com/2011/04/07/life-beyond-http-11-googles-spdy/"&gt;enabling SPDY for your web-service&lt;/a&gt;, then running on anything but some of the latest kernels won't actually give you any performance improvements! A tiny change in the TCP stack, but a big difference overall.&lt;/p&gt;

&lt;h2&gt;So what can I do about it?&lt;/h2&gt;

&lt;p&gt;TCP slow start is a feature, not a bug, and it does carry some interesting and important implications. As developers we often overlook the round trip time from the client to the server, but if we are truly interested in building a faster web, then this is a good time to investigate your options: &lt;strong&gt;re-use your TCP connections when talking to web-services, build web-services that support HTTP keep-alive and pipelining, and do think about end-to-end latency&lt;/strong&gt;. Oh, and don't waste your money on that 10Mbps+ pipe, you probably don't need it.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=mbCbT_DPQWI:DIAc6AoYUwU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/mbCbT_DPQWI" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/10/20/faster-web-vs-tcp-slow-start/</feedburner:origLink></entry><entry><title type="html">Optimizing HTTP: Keep-alive and Pipelining</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/ChRlEhW6II8/" /><updated>2011-10-04T00:00:00-07:00</updated><id>http://www.igvita.com/2011/10/04/optimizing-http-keep-alive-and-pipelining/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/http-protocol.png' class='left' /&gt;The last major update to the HTTP spec dates back to 1999, at which time &lt;a href="http://www.ietf.org/rfc/rfc2616.txt"&gt;RFC 2616&lt;/a&gt; standardized HTTP 1.1 and introduced the much needed &lt;a href="http://en.wikipedia.org/wiki/HTTP_persistent_connection"&gt;keep-alive&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/HTTP_pipelining"&gt;pipelining&lt;/a&gt; support. Whereas HTTP 1.0 required strict "single request per connection" model, HTTP 1.1 reversed this behavior: by default, an HTTP 1.1 client and server keep the connection open, unless the client indicates otherwise (via &lt;em&gt;Connection: close&lt;/em&gt; header).&lt;/p&gt;

&lt;p&gt;Why bother? &lt;strong&gt;Setting up a TCP connection is very expensive!&lt;/strong&gt; Even in an optimized case, a full one-way route between the client and server can take 10-50ms. Now multiply that three times to complete the TCP handshake, and we're already looking at a 150ms ceiling! Keep-alive allows us to reuse the same connection between different requests and amortize this cost.&lt;/p&gt;

&lt;p&gt;The only problem is, more often than not, as developers we tend to forget this. Take a look at your own code, &lt;strong&gt;how often do you reuse an HTTP connection?&lt;/strong&gt; Same problem is found in most API wrappers, and even standard HTTP libraries of most languages, which disable keepalive by default.&lt;/p&gt;

&lt;h2&gt;HTTP Pipelining&lt;/h2&gt;

&lt;p&gt;The good news is, keep-alive is supported by all modern browsers and mostly works out of the box. Unfortunately, support for pipelining is in a much worse off shape: no browsers &lt;a href="http://en.wikipedia.org/wiki/HTTP_pipelining#Implementation_in_web_browsers"&gt;support it officially&lt;/a&gt;, and few developers ever think about it. Which is unfortunate, because it can yield significant performance benefits!&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/keepalive-pipelining.png' class='left' /&gt;While keep-alive helps us amortize the cost of creating a TCP connection, pipelining allows us to break the strict "send a request, wait for response" model. Instead, we can dispatch multiple requests, in parallel, over the same connection, without waiting for a response in serial fashion. This may seem like a minor optimization at first, but let's consider the following scenario: &lt;em&gt;request 1&lt;/em&gt; and &lt;em&gt;request 2&lt;/em&gt; are pipelined, request 1 takes 1.5s to render on the server, whereas request 2 takes 1s. What is the total runtime?&lt;/p&gt;

&lt;p&gt;Of course, the answer depends on the amount of data sent back, but the lower bound is actually 1.5s! &lt;strong&gt;Because the requests are pipelined, both request 1 and request 2 can be processed by the server in parallel&lt;/strong&gt;. Hence, request 2 completes before request 1, but is sent immediately after request 1 is complete. Fewer connections, faster response times - makes you wonder why nobody advertises that their API supports HTTP pipelining?&lt;/p&gt;

&lt;h2&gt;HTTP Keep-alive &amp;amp; Pipelining in Ruby&lt;/h2&gt;

&lt;p&gt;Unfortunately, many standard HTTP libraries revert to HTTP 1.0: one connection, one request. Ruby's own net/http uses a little known behavior where by default an "Connection: close" &lt;a href="https://github.com/ruby/ruby/blob/trunk/lib/net/http.rb#L1285"&gt;header is appended to each request&lt;/a&gt;, except when you're using the block form:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;net/http&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;
&lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/?delay=1.5&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/?delay=1.0&amp;quot;&lt;/span&gt;

  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 2.5 - doh! keepalive, but no pipelining&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;With the example above we get the benefits of HTTP keep-alive, but unfortunately net/http offers no support for pipelining. To enable that, you'll have to use a &lt;a href="https://github.com/drbrain/net-http-pipeline"&gt;net-http-pipeline&lt;/a&gt;, which is a standalone library:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;net/http/pipeline&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;
&lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipelining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;reqs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;reqs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Get&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/?delay=1.5&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;reqs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Get&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/?delay=1.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="n"&gt;reqs&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1.5 - keep-alive + pipelining!&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;EM-HTTP &amp;amp; Goliath: Keep-alive + Pipelining&lt;/h2&gt;

&lt;p&gt;While pipelining is disabled in most browsers, due to many &lt;a href="http://tools.ietf.org/html/draft-nottingham-http-pipeline-01"&gt;issues related to proxies and caches&lt;/a&gt;, it is nonetheless a useful optimization for your own, or for talking to your partner API's. The good news is, Apache, Nginx, HAproxy and others support it, but the problem is that most app servers, even the ones which claim to be "HTTP 1.1", usually don't.&lt;/p&gt;

&lt;p&gt;True keep-alive and pipelining support is one of the reasons we built both &lt;a href="https://github.com/igrigorik/em-http-request"&gt;em-http-request&lt;/a&gt; and &lt;a href="https://github.com/postrank-labs/goliath"&gt;Goliath&lt;/a&gt; for our stack at PostRank. A simple example in action:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;goliath&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Echo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Goliath&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;API&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Goliath&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Params&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Goliath&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Validation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RequiredParam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;delay&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;EM&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Synchrony&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;delay&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;delay&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;em-http-request&amp;#39;&lt;/span&gt;

&lt;span class="no"&gt;EM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EM&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost:9000/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;

  &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="ss"&gt;:query&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;:keepalive&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="ss"&gt;:query&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt;  1.5 - keep-alive + pipelining&lt;/span&gt;
    &lt;span class="no"&gt;EM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Total runtime is, you guessed it, 1.5s.&lt;/strong&gt; If your public or private API's are built on top of HTTP, then keep-alive and pipelining are features you should be leveraging wherever you can.&lt;/p&gt;

&lt;h2&gt;Optimizing HTTP: Interrogate your code!&lt;/h2&gt;

&lt;div id="__ss_9534267" align="center"&gt;&lt;iframe src="http://www.slideshare.net/slideshow/embed_code/9534267" marginwidth="0" frameborder="0" height="500" scrolling="no" marginheight="0" width="600"&gt;&lt;/iframe&gt;&lt;/div&gt;


&lt;p&gt;While we love to spend time optimizing our algorithms, or making the databases faster, we often forget the basics: setting up TCP connections is expensive, and pipeling can lead to big wins. &lt;strong&gt;Do use reuse HTTP connections in your code? Does your app server support pipelining? &lt;/strong&gt;The answers are usually "no, and I'm not sure", which is something we need to change!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=ChRlEhW6II8:CzZ1DQibsiQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/ChRlEhW6II8" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/10/04/optimizing-http-keep-alive-and-pipelining/</feedburner:origLink></entry><entry><title type="html">Server-Sent Event Notifications with HTML5</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/1zclT7jAKxQ/" /><updated>2011-08-26T00:00:00-07:00</updated><id>http://www.igvita.com/2011/08/26/server-sent-event-notifications-with-html5/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/html5-logo.png' class='left' /&gt;&lt;a href="http://en.wikipedia.org/wiki/Server-sent_events"&gt;Server-Sent Events&lt;/a&gt; (SSE) have long been in the shadow of the much more often talked about WebSockets API. While WebSockets can be thought of as the "&lt;a href="http://www.igvita.com/2009/12/22/ruby-websockets-tcp-for-the-browser/"&gt;TCP for the web&lt;/a&gt;", then &lt;strong&gt;SSE is best described as the "HTML5 replacement for &lt;a href="http://en.wikipedia.org/wiki/Comet_(programming"&gt;Comet&lt;/a&gt;)"&lt;/strong&gt;. Question is, do we really need both?&lt;/p&gt;

&lt;p&gt;WebSockets allow bi-directional communication and to do so, they piggyback on the original HTTP connection and "upgrade" to the WebSocket protocol. By comparison, and as the name implies, SSE is strictly a server push protocol. Additionally, messages are encoded in UTF-8 and are newline delimited. In other words, &lt;strong&gt;the bet is that most applications primarily need to push data to the client, which means that we can simplify the API and the implementation&lt;/strong&gt; - that is where SSE comes in. Still skeptical? I was. Let's take a look under the hood.&lt;/p&gt;

&lt;h2&gt;EventSource Client API&lt;/h2&gt;

&lt;p&gt;Unlike a WebSocket connection, SSE requires no additional HTTP handshakes or "protocol upgrades". For all intents and purposes,   an SSE channel is simply a long-lived, streaming HTTP connection. This alone means that you can implement an SSE service on top of  any streaming capable HTTP server.&lt;/p&gt;

&lt;p&gt;On the browser side, the EventSource API is now supported by Chrome, Firefox 6+, Safari and Opera. To start receiving server notifications, we simply open a connection to an SSE URI and &lt;a href="http://dev.w3.org/html5/eventsource/#the-eventsource-interface"&gt;setup our callbacks&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/my/sse_endpoint&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user_login&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;open&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Connection was opened.&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventPhase&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;EventSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOSED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Connection was closed.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The API is very simple: create an EventSource connection, define your connection open, close, and message callbacks, and you are off to the races. However, the SSE API also provides a &lt;a href="http://www.html5rocks.com/en/tutorials/eventsource/basics/#toc-event-stream-format"&gt;few more built-in features&lt;/a&gt;. In the example above we added a &lt;em&gt;"user_login"&lt;/em&gt; listener - turns out, we can tag our messages! Likewise, we can provide message ID's, and the SSE source will even automatically reconnect for you if the connection is dropped.&lt;/p&gt;

&lt;h2&gt;Simple SSE Server with Goliath&lt;/h2&gt;

&lt;p&gt;The client API is nice and simple, but where the SSE spec really shines is in how simple it makes the server implementation. Whereas to power a WebSocket service you will likely need an entirely different backend, &lt;strong&gt;an SSE endpoint can be implemented by any streaming capable HTTP web server&lt;/strong&gt;. As an example, let's create a &lt;a href="http://www.igvita.com/2011/03/08/goliath-non-blocking-ruby-19-web-server/"&gt;Goliath powered&lt;/a&gt; SSE app and &lt;a href="http://www.igvita.com/2011/06/02/0-60-deploying-goliath-on-heroku-cedar/"&gt;deploy it to Heroku&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;goliath&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EventGenerator&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Goliath&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;API&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;EM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_periodic_timer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data:hello #&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="no"&gt;EM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_periodic_timer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;event:signup&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;data:signup event #&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;streaming_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;text/event-stream&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SSE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Goliath&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;API&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:urls&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/index.html&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:root&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Goliath&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;public&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/events&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="no"&gt;EventGenerator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Our Goliath server responds to requests to &lt;em&gt;/events&lt;/em&gt; by returning a 200 OK response, and then starts emitting newline delimited messages every couple of seconds - &lt;strong&gt;we're streaming plaintext messages directly into the HTTP connection&lt;/strong&gt;! Additionally, Goliath also serves a static index file, which opens an EventSource connection to our &lt;em&gt;/events&lt;/em&gt; endpoint (see the &lt;a href="https://gist.github.com/1172837"&gt;full gist here&lt;/a&gt;). With that, we can add a Procfile and a Gemfile, and push it out to Heroku: a &lt;a href="http://sse-demo.herokuapp.com/index.html"&gt;live SSE demo powered by Goliath&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;SSE vs. WebSockets&lt;/h2&gt;

&lt;p&gt;Technically speaking, the WebSockets spec is a superset of SSE and it is easy to wonder why we need both. Having said that, it is also hard not to like the simplicity of the EventSource API - both on the client, and especially on the server. Chances are, many apps won't actually need the bi-directional capabilities of WebSockets, and hence can benefit a great deal from the simplified setup and deployment enabled by SSE. Definitely an option to keep in mind.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=1zclT7jAKxQ:rf-SM-7vyhk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/1zclT7jAKxQ" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/08/26/server-sent-event-notifications-with-html5/</feedburner:origLink></entry><entry><title type="html">Rails 3 Asset Pipeline &amp; Google Closure</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/HCGAZucy8lk/" /><updated>2011-08-16T00:00:00-07:00</updated><id>http://www.igvita.com/2011/08/16/rails-3-asset-pipeline-google-closure/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/10/rails3.png' class='left' /&gt;Rails 3.1.0 is on the horizon and the new Asset Pipeline is the king of the show. If this comes as news, then make sure to check out &lt;a href="http://www.youtube.com/watch?v=cGdCI2HhfAU"&gt;DHH's keynote from RailsConf&lt;/a&gt;, and also read through the &lt;a href="http://edgeguides.rubyonrails.org/asset_pipeline.html"&gt;excellent edge guide&lt;/a&gt;. This new release brings about some of the most developer visible changes in a long time: it both makes the previously "stashed away" assets such as Javascript and CSS first class citizens in our development workflow, and also pushes us into the bold new world of &lt;a href="http://jashkenas.github.com/coffee-script/"&gt;Coffeescript&lt;/a&gt;, &lt;a href="http://sass-lang.com/"&gt;Sass&lt;/a&gt;, and many other similar tools. It's about time!&lt;/p&gt;

&lt;h2&gt;Asset Pipeline &amp;amp; Preprocessing&lt;/h2&gt;

&lt;p&gt;Under the hood, there are two major components: &lt;a href="http://getsprockets.org/"&gt;Sprockets&lt;/a&gt; is responsible for all the asset preprocessing, and there is an &lt;a href="https://github.com/sstephenson/sprockets/blob/master/lib/sprockets/server.rb"&gt;additional middleware&lt;/a&gt; (mounted under &lt;code&gt;/assets&lt;/code&gt;) which manages the actual toolchain. Hence, a request to &lt;code&gt;/assets/application.js&lt;/code&gt; will hit the middleware, which will in turn invoke Sprockets, run the minifiers and compressors, and finally return the Javascript file. Good news is, this is all basically invisible.&lt;/p&gt;

&lt;p&gt;Let's take a closer look at the default &lt;code&gt;application.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="c1"&gt;// javascript comment&lt;/span&gt;
&lt;span class="c1"&gt;//= require jquery&lt;/span&gt;
&lt;span class="c1"&gt;//= require mylib/stuff.js&lt;/span&gt;
&lt;span class="c1"&gt;//= require_tree otherlib/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The goal is to enable Rails to serve a single Javascript file back to our visitors. To accomplish this, we need to tell Rails which files and directories should be included in the output. With that in mind, and as you may have guessed, the &lt;code&gt;//=&lt;/code&gt; comment is, in fact, a &lt;a href="https://github.com/sstephenson/sprockets/blob/master/lib/sprockets/directive_processor.rb#L103"&gt;special directive for Sprockets&lt;/a&gt; to include the specified file in the processing of the asset pipeline. Just specify the files, or entire directories and the rest is taken care of. CSS handling &lt;a href="https://github.com/sstephenson/sprockets/blob/master/lib/sprockets/directive_processor.rb#L85"&gt;is no different&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Google Closure + Dependency Management&lt;/h2&gt;

&lt;p&gt;Turns out, &lt;a href="http://code.google.com/closure/library/docs/gettingstarted.html"&gt;Google's Closure library&lt;/a&gt; has a similar, but different, built-in dependency management system:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;closure-library/closure/goog/base.js&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;goog.dom&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createDom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;h1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Hello world!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Closure's DOM manipulation (&lt;code&gt;goog.dom&lt;/code&gt;) is an independent set of libraries, which are loaded by Closure at runtime when we call &lt;em&gt;goog.require&lt;/em&gt;. Now, the dynamic loading is convenient in development mode, but it would be both slow and costly in production! To address this, Closure also ships with a &lt;a href="http://code.google.com/p/closure-library/source/browse/trunk/closure/bin/calcdeps.py"&gt;separate Python script&lt;/a&gt; to preprocess your Javascript to generate the single asset file:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;closure-library/closure/bin/calcdeps.py -i hello.js -p closure-library/ -o script &amp;gt; hello-calc.js
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In other words, the net effect is the same as that provided by the built-in Asset Pipeline, but it requires manual intervention and third party tools - &lt;strong&gt;we can do better&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Extending Rails 3 Asset Pipeline: Closure support&lt;/h2&gt;

&lt;p&gt;The great news is, Sprockets allows us to easily modify and add new directive processors into our pipeline: there is no reason why we should be limited to &lt;code&gt;//=&lt;/code&gt; directives only! Closure's &lt;code&gt;goog.require's&lt;/code&gt; are effectively the same mechanism, hence we can extract these calls, load the right files, and make Closure a first class citizen in Rails! To do that, we can define a &lt;a href="https://github.com/igrigorik/closure-sprockets/blob/master/lib/closure-sprockets/processor.rb"&gt;simple Closure Preprocessor&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClosureDependenciesProcessor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Tilt&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Template&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;require_asset&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;goog/base&amp;#39;&lt;/span&gt;

    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# scan the JS file for goog.require calls&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;goog\.require\s*\(\s*[\&amp;#39;\&amp;quot;]([^\)]+)[\&amp;#39;\&amp;quot;]\s*\)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;sub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nil?&lt;/span&gt;

        &lt;span class="n"&gt;dep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sub&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;compact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;require_asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;data&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="download"&gt;&lt;a href="http://www.github.com/igrigorik/closure-sprockets/tree/master/.git"&gt;closure-sprockets&lt;/a&gt; - Sprockets processor for Google's Closure tools&lt;/div&gt;


&lt;p&gt;With that in place, we can &lt;a href="http://www.igvita.com/2010/08/04/rails-3-internals-railtie-creating-plugins/"&gt;define a new Railtie&lt;/a&gt; to &lt;a href="https://github.com/igrigorik/closure-sprockets/blob/master/lib/closure-sprockets/railtie.rb"&gt;register the new Javascript preprocessor&lt;/a&gt;, package it as a gem, and we're in business! Add the gem to your Gemfile, download the closure library, and you are good to go.&lt;/p&gt;

&lt;h2&gt;Rails 3 API's&lt;/h2&gt;

&lt;p&gt;The final &lt;a href="https://github.com/igrigorik/closure-sprockets"&gt;closure-sprockets&lt;/a&gt; gem is almost trivial and is &lt;a href="https://github.com/igrigorik/closure-sprockets/blob/master/README.md"&gt;even easier to setup within your own project&lt;/a&gt;. Having said that, this is only true because of the extensibility provided by both the Sprockets preprocessors and the Railtie integration - &lt;strong&gt;kudos to the Rails 3 team for putting together these great API's&lt;/strong&gt;. Finally, thanks to &lt;a href="https://github.com/josh"&gt;Josh&lt;/a&gt; for &lt;a href="https://github.com/rails/rails/issues/2211"&gt;hand-holding me through the process&lt;/a&gt; of learning about Sprockets and the new Asset Pipeline!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=HCGAZucy8lk:uwLMELAOrZw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/HCGAZucy8lk" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/08/16/rails-3-asset-pipeline-google-closure/</feedburner:origLink></entry><entry><title type="html">Protocol Buffers, Avro, Thrift &amp; MessagePack</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/cxsCY-GeA5A/" /><updated>2011-08-01T00:00:00-07:00</updated><id>http://www.igvita.com/2011/08/01/protocol-buffers-avro-thrift-messagepack/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/avro-fb-gb-json.png' class='left' /&gt;Perhaps one of the first inescapable observations that a new Google developer (&lt;em&gt;Noogler&lt;/em&gt;) makes once they dive into the code is that &lt;a href="http://code.google.com/p/protobuf/"&gt;Protocol Buffers&lt;/a&gt; (PB) is the "language of data" at Google. Put simply, &lt;strong&gt;Protocol Buffers are used for serialization, RPC, and about everything in between&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Initially developed in early 2000's as an optimized server request/response protocol (hence the name), they have become the de-facto data persistence format and RPC protocol. Later, following a major (v2) rewrite in 2008, Protocol Buffers was &lt;a href="http://google-opensource.blogspot.com/2008/07/protocol-buffers-googles-data.html"&gt;open sourced by Google&lt;/a&gt; and now, through a number of &lt;a href="http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns"&gt;third party extensions&lt;/a&gt;, can be used across dozens of languages - including Ruby, of course.&lt;/p&gt;

&lt;p&gt;But, Protocol Buffers for &lt;em&gt;everything?&lt;/em&gt; Well, it appears to work for Google, but more importantly I think this is a great example of where &lt;strong&gt;understanding the historical context in which each was developed is just as instrumental as comparing features and &lt;a href="https://github.com/eishay/jvm-serializers/wiki/"&gt;benchmarking speed&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Protocol Buffers vs. Thrift&lt;/h2&gt;

&lt;p&gt;Let's take a step back and compare Protocol Buffers to the "competitors", of which there are plenty. Between PB, &lt;a href="http://thrift.apache.org/"&gt;Thrift&lt;/a&gt;, &lt;a href="http://avro.apache.org/"&gt;Avro&lt;/a&gt; and &lt;a href="http://msgpack.org/"&gt;MessagePack&lt;/a&gt;, which is the best? Truth of the matter is, they are all very good and each has its own strong points. Hence, the answer is as much of a personal choice, as well as understanding of the historical context for each, and correctly identifying your own, individual requirements.&lt;/p&gt;

&lt;p&gt;When Protocol Buffers was first being developed (early 2000's), the preferred language at Google was C++ (nowadays, Java is on par). Hence it should not be surprising that PB is strongly typed, has a separate schema file, and also requires a compilation step to output the language-specific boilerplate to read and serialize messages.  To achieve this, Google defined their own language (&lt;a href="http://en.wikipedia.org/wiki/Interface_description_language"&gt;IDL&lt;/a&gt;) for specifying the proto files, and limited PB's design scope to efficient serialization of common types and attributes found in Java, C++ and Python. Hence, &lt;strong&gt;PB was designed to be layered over an (existing) RPC mechanism&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/facebook-thrift.png' class='left' /&gt;By comparison, Thrift which was &lt;a href="http://www.igvita.com/2007/11/30/ruby-web-services-with-facebooks-thrift/"&gt;open sourced by Facebook in late 2007&lt;/a&gt;, looks and feels very similar to Protocol Buffers - in all likelihood, there was some design influence from PB there. However, unlike PB, &lt;strong&gt;Thrift makes RPC a first class citizen&lt;/strong&gt;: Thrift compiler provides a variety of transport options (network, file, memory), and also tries to target &lt;a href="http://wiki.apache.org/thrift/LibraryFeatures?action=show&amp;amp;redirect=LanguageSupport"&gt;many more languages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Which is the &lt;em&gt;"better"&lt;/em&gt; of the two? Both have been production tested at scale, so it really depends on your own situation. If you are primarily interested in the binary serialization, or if you already have an RPC mechanism then Protocol Buffers is a great place to start. Conversely, if you don't yet have an RPC mechanism and are looking for one, then Thrift may be a good choice. &lt;em&gt;(Word of warning: historically, Thrift has not been consistent in their feature support and performance across all the languages, so &lt;a href="http://floatingsun.net/articles/thrift-vs-protocol-buffers/"&gt;do some research&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Protocol Buffers vs. Avro, MessagePack&lt;/h2&gt;

&lt;p&gt;While Thrift and PB differ primarily in their scope, &lt;strong&gt;Avro and MessagePack should really be compared in light of the more recent trends: rising popularity of dynamic languages, and JSON over XML&lt;/strong&gt;. As most every web developers knows, JSON is now &lt;a href="http://json.org/"&gt;ubiquitous&lt;/a&gt;, and easy to parse, generate, and read, which explains its popularity. JSON also requires no schema, provides no type checking, and it is a UTF-8 based protocol - in other words, easy to work with, but not very efficient when put on the wire.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MessagePack is effectively JSON, but with efficient binary encoding.&lt;/strong&gt; Like JSON, there is no type checking or schemas, which depending on your application can be either be a pro or a con. But, if you are already streaming JSON via an API or using it for storage, then MessagePack can be a drop-in replacement.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/avro.png' class='left' /&gt;&lt;strong&gt;&lt;a href="http://avro.apache.org/"&gt;Avro&lt;/a&gt;, on the other hand, is somewhat of a hybrid. In its scope and functionality it is close to PB and Thrift, but it was &lt;a href="http://www.igvita.com/2010/02/16/data-serialization-rpc-with-avro-ruby/"&gt;designed with dynamic languages in mind&lt;/a&gt;&lt;/strong&gt;. Unlike PB and Thrift, the Avro schema is embedded directly in the header of the messages, which eliminates the need for the extra compile stage. Additionally, the schema itself is just a JSON blob - no custom parser required! By enforcing a schema Avro allows us to do data projections (read individual fields out of each record), perform type checking, and enforce the overall message structure.&lt;/p&gt;

&lt;h2&gt;"The Best" Serialization Format&lt;/h2&gt;

&lt;p&gt;Reflecting on the use of Protocol Buffers at Google and all of the above competitors it is clear that there is no one definitive, &lt;em&gt;"best"&lt;/em&gt; option. Rather, each solution makes perfect sense in the context it was developed and hence the same logic should be applied to your own situation.&lt;/p&gt;

&lt;p&gt;If you are looking for a battle-tested, strongly typed serialization format, then Protocol Buffers is a great choice. If you also need a variety of built-in RPC mechanisms, then Thrift is worth investigating. If you are already exchanging or working with JSON, then MessagePack is almost a drop-in optimization. And finally, if you like the strongly typed aspects, but want the flexibility of easy interoperability with dynamic languages, then Avro may be your best bet at this point in time.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=cxsCY-GeA5A:T9TW7LN6hys:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/cxsCY-GeA5A" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/08/01/protocol-buffers-avro-thrift-messagepack/</feedburner:origLink></entry><entry><title type="html">HTML5 Visibility API &amp; Page Pre-Rendering</title><link rel="alternate" type="text/html" href="http://feeds.igvita.com/~r/igvita/~3/u6FkWwoTiKg/" /><updated>2011-06-25T00:00:00-07:00</updated><id>http://www.igvita.com/2011/06/25/html5-visibility-api-page-pre-rendering/</id><content type="html">&lt;p&gt;&lt;img src='http://www.igvita.com/posts/11/html5-logo.png' class='left' /&gt;Minimizing UI latency is critical for creating a positive user experience - this is true both on the desktop and on the web. A best practice for a "native app" is to decouple the UI and control threads to avoid blocking on any long-running tasks. On the web, things are a lot trickier: our Javascript runtimes are all single-threaded, we can't just spin up an extra thread, and instead have to rely on event-driven programming models. Even worse, unless the invoked computation is local, a roundtrip to the server can easily take hundreds of milliseconds in the network overhead alone.&lt;/p&gt;

&lt;p&gt;Not surprisingly, over the course of the past few years we have invented dozens of new Javascript based UI frameworks: all asynchronous, all focused on trying to hide the interaction latency behind a Javascript facade. In theory, all great ideas, but in practice also with their own set of downsides: &lt;a href="http://www.jenitennison.com/blog/node/154"&gt;how about those #!'s&lt;/a&gt;, and we have all certainly seen and written a few &lt;a href="http://www.w3schools.com/js/js_timing.asp"&gt;overly eager setTimeout's&lt;/a&gt; which quickly destroy the clients CPU and battery life.&lt;/p&gt;

&lt;p&gt;In fact, because the browser VM is a shared resource, we have a classic &lt;a href="http://en.wikipedia.org/wiki/Tragedy_of_the_commons"&gt;tragedy of the commons&lt;/a&gt;: if every application plays nice, then everyone can have an optimal experience, but the incentives to do so are not clear. Problem is, until very recently we did not even have the tools to address this issue! &lt;a href="http://www.w3.org/TR/2011/WD-page-visibility-20110602/"&gt;Page Visibility API&lt;/a&gt; is the first HTML5 proposal that is trying to tackle this problem, and browser &lt;a href="http://code.google.com/chrome/whitepapers/prerender.html"&gt;pre-rendering&lt;/a&gt; is also aiming to help us hide some of the network latency in our web applications - let's take a look under the hood.&lt;/p&gt;

&lt;h2&gt;Browser Pre-fetching vs. Pre-rendering&lt;/h2&gt;

&lt;p&gt;An average page render requires fetching a dozen resources alongside the actual HTML content. If you dig into your debug console, it is not uncommon to see pages which take on the &lt;a href="http://news.cnet.com/8301-13846_3-20072653-62/the-web-is-taking-too-long-infographic/"&gt;order of ten seconds to load&lt;/a&gt; to completion. Thankfully, the browsers have implemented many tricks to make it seem as if the page is loading much faster - parallel downloads, highly optimized rendering engines, and a never ending battle to speed up Javascript execution. Nonetheless, usually this is still not enough to beat the "native experience".&lt;/p&gt;

&lt;p&gt;Well, the server can help us as well: &lt;a href="http://www.igvita.com/2011/04/07/life-beyond-http-11-googles-spdy/"&gt;new protocols like SPDY&lt;/a&gt; are aiming to reduce the network overhead of fetching multiple resources, and there is even talk of enabling &lt;a href="http://www.chromium.org/spdy/spdy-whitepaper"&gt;server push&lt;/a&gt; of related page assets. Think you can guess what the user may click on next? Firefox 3.5 enabled the &lt;a href="https://developer.mozilla.org/en/Link_prefetching_FAQ"&gt;pre-fetching API&lt;/a&gt; which allows us to hint to the browser what resources it may need to service a subsequent request:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="c"&gt;&amp;lt;!--  Specify any &amp;amp; all resources to pre-fetch --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;prefetch&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/images/big.jpg&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- or send an HTTP header --&amp;gt;&lt;/span&gt;
Link: &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;/images/big.jpeg&amp;gt;; rel=prefetch
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Pre-fetching is a simple optimization, but it requires that we explicitly specify each and every resource - just listing the link of the next HTML page is unlikely to result in a noticeable improvement in the user experience.&lt;/p&gt;

&lt;p&gt;This is where the new &lt;strong&gt;pre-rendering&lt;/strong&gt; proposal comes in: &lt;strong&gt;instead of specifying a single resource, what if the browser could fetch and render the entire next page, but hide it from you until you click on the link?&lt;/strong&gt; As of &lt;a href="http://code.google.com/p/chromium/issues/detail?id=83286"&gt;about a month ago&lt;/a&gt;, pre-rendering support is in WebKit and Google is already prototyping it with "Instant Pages":&lt;/p&gt;

&lt;p align="center"&gt;&lt;iframe allowfullscreen src="http://www.youtube.com/embed/_Jn93FDx9oI" frameborder="0" height="371" width="600"&gt;&lt;/iframe&gt;&lt;/p&gt;


&lt;h2&gt;Pre-rendering wins and gotchas&lt;/h2&gt;

&lt;p&gt;At the moment, the &lt;a href="http://code.google.com/chrome/whitepapers/prerender.html"&gt;pre-rendering API&lt;/a&gt; is limited: only one page can be pre-rendered across the entire VM, and only one page can be put into the pre-render queue per tab. Fetching an entire page taxes both the server and the client, hence you need be sure that you will actually need it. Google's web search team, for example, only enables pre-rendering on search results if they have very &lt;em&gt;high confidence&lt;/em&gt; that you may actually click on the result.&lt;/p&gt;

&lt;p&gt;Additionally, since we are now pre-rendering the entire page (HTML, CSS, and JS), how does this affect all the interactive content on the page? Knowing nothing about the pre-render step, the requested page can easily pin our CPU, register a pageview and make a request to an ad server for content that the user may never actually see! To solve this problem, WebKit developers have also added the &lt;a href="http://www.w3.org/TR/2011/WD-page-visibility-20110602/"&gt;Page Visibility API&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleVisibilityChange&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;webkitHidden&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;pausePageJavascript&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;startPageJavascript&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;webkitvisibilitychange&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleVisibilityChange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;webkitHidden&lt;/code&gt; property tells us the state of the page to solve the original visibility problem, but the &lt;code&gt;webkitvisibilitychange&lt;/code&gt; event has another nice side effect: it allows the client to easily detect when a tab is visible, and when it is in the background. Why does this matter? Imagine you have an application which polls the client, or the server, every 50 milliseconds for some updates. &lt;strong&gt;With the visibility API, you can &lt;a href="http://code.google.com/chrome/whitepapers/pagevisibility.html"&gt;gracefully pause or degrade the timer&lt;/a&gt; to a much longer poll when the tab is in the background.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Minimizing latency on the web&lt;/h2&gt;

&lt;p&gt;Both pre-rendering and Page Visibility API's are still in development, but it is great to see more client-side tools to enable web developers to hide the underlying network latency. With these API's, instead of relying on an async Javascript stack, your next multi-step form can be rendered on the server and pre-rendered in a WebKit browser with instant feedback on the client!&lt;/p&gt;

&lt;p&gt;Likewise, while browsers like Chrome are already downgrading background tabs in CPU priority, a client-side API to detect foreground tabs is a welcome addition. Let's hope that Firefox, Opera and IE jump on the bandwagon as well!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.igvita.com/~ff/igvita?a=u6FkWwoTiKg:UjJAOZWV6fA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/igvita?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/igvita/~4/u6FkWwoTiKg" height="1" width="1"/&gt;</content><feedburner:origLink>http://igvita.com/2011/06/25/html5-visibility-api-page-pre-rendering/</feedburner:origLink></entry></feed>

