After a couple of failed stabs at testing the relative speed of window.localStorage versus client-side databases, Ryan Grove and Can Duruk pointed out that my tests were not taking into account the asynchronous nature of the APIs. So, here is what I think is a more correct test of the relative speeds. Turns out it makes a huge difference when you test things correctly!
On my MacBook Pro in desktop Safari, I'm seeing the DOM storage test take ~0.1ms per set of operations and ~10ms per set of operations for SQL storage. At that speed, the difference would be imperceptible to end-users. However, on my iPhone 3G, I'm seeing ~1ms per set of ops for DOM storage versus ~140ms for SQL. Now we're talking about a difference users might notice. This test shows me it pays to carefully consider whether the extra power of SQL is worth the speed cost on meek devices.
Iterations:
// TEST SETUP function Timer() { this.start = 0 this.duration = 0 } Timer.prototype = { go : function () { this.duration = 0 this.start = +new Date }, stop : function (el) { var timer = this setTimeout(function () { timer.duration = +new Date - timer.start timer.start = 0 timer.write(el) }, 0) }, write : function (el) { el.innerHTML = this.duration + 'ms' } } function getIters() { var sel = document.getElementById('iters') return +sel.options[sel.selectedIndex].value } // data var someData = { 'key' : 'my-uuid', 'name' : 'Fugly McFunston', 'rank' : 'Junior Leftenant', 'serial-number' : 'ABC123' }; var lawnchair_dom = new Lawnchair({ adaptor : 'dom' }); var lawnchair_sql = new Lawnchair({ table : 'segdeha', adaptor : 'webkit' }); function startDOM() { var iters = getIters(), i = 0, timer = new Timer(), el = document.getElementById('result-dom') el.innerHTML = '--' function run() { var myData lawnchair_dom.nuke() lawnchair_dom.save(someData, function() { lawnchair_dom.get('my-uuid', function(r) { myData = r lawnchair_dom.remove('my-uuid', function () { ++i if (i < iters) run() else timer.stop(el) }) }) }) } timer.go() run() } function startSQL() { var iters = getIters(), i = 0, timer = new Timer(), el = document.getElementById('result-sql') el.innerHTML = '--' function run() { var myData lawnchair_sql.nuke() lawnchair_sql.save(someData, function() { lawnchair_sql.get('my-uuid', function(r) { myData = r lawnchair_sql.remove('my-uuid', function () { ++i if (i < iters) run() else timer.stop(el) }) }) }) } timer.go() run() }