Just a quick post to say that State of the Browser 2012 was awesome. I had loads of fun, met a lot of great new people and heard loads of really interesting talks.
If you couldn’t make it, sad times, but we streamed the whole thing live on the website. Vimeo videos will be on the website soon, direct yourself to browser.londonwebstandards.org for the goodies.
February 2012′s London Web Standards event at Forward London was an introduction to Node.js, the server-side javscript framework designed for high concurrency and real-time events. There were two sessions at the event, George Ornbo (@shapeshed) giving an introduction to Node, and a “Node & Tell” session, where four sets of developers came and told the gathered crowd how they’d been using Node in their work.
LWSNode - George Ornbo
Introduction to Node.js – George Ornbo
George is a front-end javascript developer who wanted a simpler way to create web apps quickly, and in a language that he knows. Enter Node.js, with its “Event driven I/O”, or better put as “Network programming with javascript”.
George fired up his browser, and gave the attendees the IP address of his laptop, which was running a simple Node.js chat server, which coped incredibly well with 100 people trying to join from their phones and laptops, showing how resilient it can be on a small laptop. We were then treated to a demo of a “Love/Hate” measure, taking a data feed from Twitter in real-time, it counted and displayed a graph of the percentage of love and hate on Twitter within the last 10 minutes. Seeing the data streaming in, and then the 30 lines of code used to create that was amazing. Node is a framework that does all the hard stuff for you, and enables you to write applications quickly and efficiently.
George then explained why it was so fast – Node works on an event loop, rather than threads. The idea is that no operation should be blocking so that Node can always keep getting http requests and fire of requests to the database or any other data sources asyncronously. It’s a big of a head scratcher to anyone who hasn’t done much high-performance javascript before, but it’s a very efficient way to program. George showed two graphs (roughly transcribed to the notes) on node performance vs apache for high concurrency and memory usage: node wipes the floor with it. Note: since this talk took place, Apache 2.4 has come out. These graphs are a bit different now but Ngix is still well ahead on speed
In summary, Node is great for high concurrency situations and for making server back-ends quickly. It’s a break from your normal programming style but is is just JavaScript when you’re over that hurdle. Give it a go!
Node and Tell Sessions
Node & Tell
All of these 4 people gave it a go and were kind enough to show us what they’d been doing.
First was Maired Buchan from Head who had made a voting system based on an Arduino and Node to collect the data. Other than that the voting machine use marble runs to capture votes, she explained that they’d tried a number of places to put the Node server to get maximum performance, eventually settling on a separate server, allowing the Arduino to just count and send a message to Node. The source code is now on GitHub.
The second talk was from Andrew Nesbitt talking about the London Node User Group (which me mentioned on and off), and showing off how he’d made the LNUG website with Node and GitHub.
The third talk was Simon Thompson talking about how he’s used Node as a prototyping language, making a drag & drop filing cabinet backed by a MongoDB. He was really impressed with how simple everything was and how little setup you needed to do before everything was working.
The final talk from Daniel Knell and Jason Grant showed a responsive web app that found interesting things to do in your local area. Using Node to help them make some of the more complex geolocation calculations, the web app is a very simple idea that is well executed. It is so good that it won first place at a recent hack day, and they finished in half the time they were given.
If you follow any front-end web developers on Twitter today, you’ll probably have come across articles on vendor prefixes and the latest CSSWG fight over Mozilla, Microsoft and Opera wanting to implement -webkit- vendor prefixes. Before I delve into why this is happening, I want to make something very clear - this is wrong and must not happen.
So why is it happening?
The February 2012 face-to-face meeting of the CSSWG [complete transcript] had vendor prefixes on the agenda because:
glazou: Title is: Why and How to Implement Other Vendors' Prefixes
tantek: This is a specific subtopic of vendor prefixes
tantek: The problem statement right now, and this is a problem for
Mozilla and any other non-WebKit browser
tantek: Sites have webkit-specific content, and serve backup content to
everyone else. Specifically for mobile content.
tantek: Non-WebKit browsers face prisoners dilemma
tantek: similar to quirks in 2003 or so
FYI: glazou is Daniel Glazman, chair of the CSSWG, tantek is from Mozilla. Other parties who appear in quotes are Peter Linss (HP), Florian Rivoual (Opera), Sylvain Galineau (Microsoft) and Simon Fraser (smfr from Apple).
So far, sounds reasonable, then tantek continues:
tantek: At this point we're trying to figure out which and how many webkit
prefix properties to actually implement support for in Mozilla
plinss: Zero.
tantek: Currently we have zero. Zero is no longer an option for us.
Suddenly, everything is turned upside down. Opera and Microsoft start saying the same thing – the argument is that of the top 1000 websites, a significant percentage uses webkit-only prefixes without the other browser prefixes.
glazou: A long time ago, Mozilla had an Evangelism team that would call up
the website owners and ask them to change.
This refers to developer evangelism, people like Bruce Lawson, Martin Beeby and Rob Hawkes to name just three (Google has a huge team - [Thanks to Michael for the correct link]). All of these people are pioneers in web technology and use vendor prefixes every day, and all of them tell developers to use the other browser’s vendor prefixes too. This is not the opinion of the CSSWG:
Florian, Sylvain: Evangelism has failed.
glazou: Have you tried pinging the WASP about that? Other activists of web
standards?
sylvaing: If MS can't scale to handle this, you think WASP can?
tantek: Opposite is happening right now. Web standards activists are teaching
people to use -webkit-
tantek: People like Lea Verou.
tantek: Their demos are filled with -webkit-. You will see presentations
from all the web standards advocates advocating people to use
-webkit- prefixes.
These words make me sad indeed. The CSSWG has lost faith in evangelists and the community upon which it relies so much that they are prepared to implement other vendor’s non-standard code and prefixes to help them gain market share back.
Quirks mode all over again
Yes, this is where we’re at. The current dominance of webkit, especially on mobile, is causing developers to adopt non-standard technology and only those bits of technology for webkit. This cannot happen. Daniel Glazman understands:
tantek: What are the thresholds, even approximate, for implementing
-webkit- properites (or none)?
glazou: Unbelieveable we are having this discussion.
Florian: Our job is to solve interoperability. We want to discuss it here,
because that's our job.
tantek: Help us minimize the damage.
There are two problems that have been raised: that webkit has an “IE6 style” dominance over mobile, and that developers are making matters worse.
Time for action
The first problem is not a problem at all. It is a symptom of developer knowledge being controlled by the “latest sexy and experimental technology”. Developers are fixated on making all of those great effects that we used to have with Flash work on iPads and iPhones, and because that’s webkit only, they pay no attention to the other browsers that can use their sites. Web standards is going backwards, and it’s our fault. It’s not Apple’s, it’s not Google’s, they simply make technology available, we produce code that only targets them.
The first step is to admit that there is a problem. Look at your code. If there is a vendor prefix for any property ask yourself why you chose to use it. If there’s a good reason (like 2d transforms are cool) then look closer – have you put all of the other vendor prefixes there as well? Have you checked the syntax to make sure it’s the same (because that’s what vendor prefixes are for). One final thing is to make sure you never do it again. There’s tools to help like prefix-free and SASS and LESS CSS pre-processors all do this for you.
Fucking drop experimental prefixes. It’s unacceptable and a disservice to the developers working with your browser. You need to give timelines to dropping these things.
Non-production ready browsers should support experimental prefixes, production ready releasesshould not. If it’s Chrome 16 – the stable version – experimental support should not be baked in. The properties should be full available without the prefix.
Work with the working groups (…Apple).
I especially like item 2 here. Too many developers use dev channels as their main browser (I know I do). This is fine, but by removing prefixes from stable browser versions has the great advantage of breaking for your clients who will be on the stable channel. This will raise bugs and force developers to change their code. It works for me has never been a good excuse, and with this change it never will be.
Make some noise, Internet
None of these changes will be made if we don’t get the evangelism community back on its feet. For too long have we assumed that everything is hunky-dory now that HTML5 has ridden in and saved us from non-standard implementations. I implore you, blog about this, shout about this, tell your friends and make them review their code. Vendor prefixes are here to stay, and so are the five major browsers. You must code for all of them, all the time. Shout it from the rooftops, the only good vendor prefix, is every vendor prefix.
In my work, I’m parsing web services all of the time. Most of the time, they’re XML, which does not make the best use of bandwidth/CPU time (compared to JSON), however, if it’s all that you’re given then you can certainly get by. I’ve been looking into ways to speed up the XML document traversal in with jQuery after the current best practice method was removed.
The basic way to find certain nodes in an XML web service is to use the .find() method. This is used heavily by the SPServices jQuery helper (which is, in general, a great library).
$(xData.responseXML).find("[nodeName='z:row']").each(function(){// Do stuff});
That’s absolutely fine – it’s going to find the attribute nodeName with a value of z:row. However, since jQuery 1.7, this method does not work. I raised this regression in the jQuery bug tracker and was encouraged to find a solution; another selector that worked in all browsers. Unfortunately, at the time I couldn’t come up with anything better than this:
$(xData.responseXML).find("z\\:row, row").each(function(){// Do stuff});
The “z\\:row” selector works in IE and Firefox, and the “row” selector works in Chrome and Safari (I’m unable to test in Opera here, sorry). This was flagged as the solution to the problem and they wouldn’t be making any fixes to the jQuery core.
After a few weeks of using this method, I noticed that the site had been slowing down, especially in IE, and I thought this new selector was the cause. So, I looked into the performance numbers using jsPerf and I raised a bug too. My first test was to see what the current solution was doing, and whether jQuery 1.7 had made things worse.
Test case: http://jsperf.com/node-vs-double-select/4
So, performance in Chrome is identical for each of the selectors (and it’s the same in Firefox and Safari) but IE drops nearly half of its operations because it has to perform that second selector.
It’s still not very high performance though, and so I looked for other solutions.
Dmethvin suggested:
Did you try the custom plugin in the ticket? If you’re having performance issues that should be much faster.
This filters content by their nodeName and compares it against the name that you gave it. The issue with this is that .filter() does not traverse down the tree, staying at the level of the set of objects that it was given. Therefore, a quick solution was this:
$(xData.responseXML).children().children().children().children().children().children().children().filterNode('z:row').each(function(){// Do stuff});
Wow, that’s about 50 times faster. Even IE beats Chrome when doing this operation. The simple reason is that it’s got a smaller set of objects to go through and it’s comparing a single attribute rather than parsing the text of the XML to try and find the namespaced element.
Still, I wasn’t satisfied as in order to achieve that performance, I had to know how deep I was going to be going in order to retrieve the set. So, back to the bug and another suggestion by dmethvin:
If you’re going that deep, use a filter function passed to .find(). How does that fare?
After a few attempts, a colleague of mine came up with this beauty:
Using .find(‘*’).filter() increased performance to 200x faster than the original .find(‘z:row’) selector
I mean, wow, that’s incredible. On the graph, those tiny little bits of colour are the original selectors, and those only 20% of the way up are the previous massive performance increase by using filter. It should also be noted that IE8 performance using this selector increased in jQuery 1.7 in comparison to when using jQuery 1.6.
Side-note: IE10′s javascript performance is almost equal to that of Google Chrome. In comparison, IE9 (not shown) is about half of that.
The reason for this massive increase is that it’s backed by native selectors. A .find(‘*’) will translate into element.querySelectorAll(‘*’) which is very fast when compared to doing 8 .children() calls.
Summary
Dealing with large amounts of data from web services needs to be fast. Using a simple .find() on the node name no-longer works and alternatives have been investigated. The fastest method, using a short one-line plug-in, improves performance by up to 2000% compared to the old methodology.
I’ll be notifying the SPServices group of this post, and hopefully they can improve the performance of their library.