How much code in the browser is too much?
by Kevin Dangoor
With the ascent of AJAX, many people are writing or considering writing more code to run in browser than they had in years. JavaScript, once left for dead as being too incompatible and impossible to debug, is now being viewed as something usable.
Firefox/Mozilla has certainly helped the renaissance. With an honest-to-goodness debugger, plus a super-handy web developer toolbar, you can really get a view into once going on. Selenium provides a mechanism to run tests in-browser, so that you can get all of the benefits of an automated test suite making sure your code works in different browsers.
All of this recent goodness is causing people to start approaching JavaScript as a real programming language. However, JavaScript is still implemented a bit differently between browsers, and its object model is definitely different from what most people are used to. Ian Bicking wrote about his troubles working with Prototype.js’s extended object model. Bob Ippolito has been writing all month about JavaScript warts when it comes to real programming.
If you take a look at the kinds of things that Bob is implementing, you’ll get the idea that Bob is trying to do real development in-browser, turning it into a real layer in an application. Given that people have made sophisticated email programs and spreadsheets in JavaScript, people have certainly done this before. But, most of the scripts I’ve seen have been focused on whizzy special effects.
So, to the question then: how much should you do with JavaScript? For just about any application, I would say that the answer is “as much as you can”. Assuming you don’t have some weird requirement to support Netscape 4.x or IE on the Mac, and I feel sorry for you if you do, you can reasonably do quite a bit in JavaScript. The limiting factor will likely be JavaScript performance.
JavaScript is slow. Don’t believe me? Check out something computationally intensive like encryption or trying doing an XSL transform without native browser support (you’ll have to use Safari for that, to see what I mean).
The benefit to using JavaScript can be huge, though. Even though it is slower than the language being used on the server side, that work is being done off of your server. If you’re careful about how much data you feed to the browser to process, quite a bit of the formatting work can be offloaded there. And, if you take advantage of native code as much as possible, you can even handle fairly sizable chunks of data.
Given the value in doing JavaScript today, a framework like Bob Ippolito’s MochiKit that extends JavaScript’s object model can seriously ease the burden of putting together robust code that runs in-browser. JavaScript is definitely entering a new era.
About js speed… js sorting is SLOW. I am sorting tables in the client, by using javascript list.sort(sort_func) on the list of TRs. It is ok for small numbers of rows, but really slows down as the num of rows increases. For example, in a table with about 1200 rows, on safari, on a 667MHz Powerbook, it takes about 2 mins, and blocks all other safari windows for that time. On Firefox, same table, same machine, it takes less than half that time, but still unacceptably slow. This execution time also includes additional overhead of doing a stable sort, via the decorate-sort-undecorate paradigm.
I’d add also that I have also tested with number of rows > 1200… basically the browser never comes out of it! No patience to collect the actual metrics… ;-(
BTW, I look forward to Bob’s upcoming MochiKit…
I should hope that JavaScript’s sort function is implemented in C and is your typical quicksort or other O(n log n) function. I would guess that there is some optimization you can do. Your sort_func would be plain, interpreted JS and is going to run n log n times, so it’s worth seeing if there are optimization there.
With dynamic languages like JavaScript or Python, some optimizations are very non-obvious. You just have to try different ways of expressing the same thing and see if any of them are faster. I’m sure there are tips out there as well.
Beyond that, are you displaying 1200 rows? That’s a lot of data to actually toss up on the screen. If users don’t actually want to see 1200 rows at a time, there are likely other optimizations you can do around showing just a subset.
BTW, I’m not disputing what you’re saying: JavaScript is definitely slow, particularly in Safari. But, there may be tricks you can pull to accomplish what you’re trying to do.
I am sorting this kind of an array of html table rows:
for (var i=0, length=rows.length; i
I am sorting this kind of an array of html table rows:
for (var i=0, length=rows.length; i<length; i++) {
// remember current index, to stabilize sort
reorderedRows[i] = [ rows[i].cloneNode(true), i ];
}
and the sort_func used in reorderedRows.sort(sort_fun) looks like the following (replace TYPE as appropriate):
function rowCompareTYPE(a, b) {
var aVal = parseTYPE(a[0].getElementsByTagName(‘td’)[_g_stbl_sortOn_].firstChild.nodeValue);
var bVal = parseTYPE(b[0].getElementsByTagName(‘td’)[_g_stbl_sortOn_].firstChild.nodeValue);
if (aVal == bVal) { return (a[1] – b[1]); }
else { return (bVal – aVal); }
}
Now, maybe if I was not looking into a dom subtree each time it might go a lot quicker. Have not tested it. Anyone see anything obvious to optimize this?
Another annoyance… the _g_stbl_sortOn_ is a global variable, that I am setting before calling the sort function. This is because I know of no way to bind the sort function to the “js table” instance, thus giving it access to private members — allowing multiple sortable tables in the same page, safely. Rather hacky…
As for showing 1200 rows in a single table — it is not of course very practical, but I am showing it. If sorting was fast enough on the client, whether the actual rows are shown or not would be a superficial issue. One can allow the user to simply specify a preferred number of rows to show, and then just use css to “hide” the rest of them… but the sorting can still work on the full data set, on the client, thus, no AJAX necessary
My guess, and it’s really just a guess, is that all of those DOM lookups may be slower than is healthy. What you might want to do is generate a page that has just an array of the values you want to sort (no tables involved) and sort with a really trivial sort function to see what a best-case scenario is. If that best-case scenario turns out to be reasonable, you can think about doing something like storing the data in an array and then regenerate the table from the array after sorting it.
It is worth seeing what the best possible time is first, though… if sorting 1,200 items with a trivial sort function is too slow, you either need to go AJAX or think about not displaying all 1,200 rows. (I believe there’s an algorithm for doing something like; display the 50 entries that score the highest that is O(n log n) worst case, and possibly better).