WRITE operations in IndexedDB vs localStorage vs webSQL

JavaScript performance comparison

Revision 2 of this test case created

Info

This test mirrors my modified version of this test: http://jsperf.com/indexeddb-vs-localstorage/15

I wanted a way to test the two distinct operations, READ and WRITE separately. I felt that testing them together was fatally flawed against async operations and didn't fairly highlight the strong points of the different storage mechanisms.

Preparation code

<script src="https://raw.github.com/jensarps/IDBWrapper/master/idbstore.js">
<script>
  var scope = {};

  // store setup
  var idb = new IDBStore({
    dbName: 'jsperftestdb',
    storeName: 'jsperfteststore',
    dbVersion: '1.0',
    keyPath: 'id',
    autoIncrement: true,
    onStoreReady: function() {
      idb.clear();
    }
  });
  var ls = window.localStorage;
  ls.clear();


  var websql = openDatabase('benchmark', '1.0', '', 1 * 1024 * 1024);
  websql.transaction(function(tx) {
    tx.executeSql('DROP TABLE IF EXISTS benchmark;');
    tx.executeSql('CREATE TABLE benchmark (id, value);');
  });

  // data setup
  var i = 0,
      lastnames = ['smith', 'miller', 'doe', 'frankenstein', 'furter'],
      firstnames = ['peter', 'john', 'frank', 'james'],
      dummyData = {
      "web-app": {
        "servlet": [{
          "servlet-name": "cofaxCDS",
          "servlet-class": "org.cofax.cds.CDSServlet",
          "init-param": {
            "configGlossary:installationAt": "Philadelphia, PA",
            "configGlossary:adminEmail": "ksm@pobox.com",
            "configGlossary:poweredBy": "Cofax",
            "configGlossary:poweredByIcon": "/images/cofax.gif",
            "configGlossary:staticPath": "/content/static",
            "templateProcessorClass": "org.cofax.WysiwygTemplate",
            "templateLoaderClass": "org.cofax.FilesTemplateLoader",
            "templatePath": "templates",
            "templateOverridePath": "",
            "defaultListTemplate": "listTemplate.htm",
            "defaultFileTemplate": "articleTemplate.htm",
            "useJSP": false,
            "jspListTemplate": "listTemplate.jsp",
            "jspFileTemplate": "articleTemplate.jsp",
            "cachePackageTagsTrack": 200,
            "cachePackageTagsStore": 200,
            "cachePackageTagsRefresh": 60,
            "cacheTemplatesTrack": 100,
            "cacheTemplatesStore": 50,
            "cacheTemplatesRefresh": 15,
            "cachePagesTrack": 200,
            "cachePagesStore": 100,
            "cachePagesRefresh": 10,
            "cachePagesDirtyRead": 10,
            "searchEngineListTemplate": "forSearchEnginesList.htm",
            "searchEngineFileTemplate": "forSearchEngines.htm",
            "searchEngineRobotsDb": "WEB-INF/robots.db",
            "useDataStore": true,
            "dataStoreClass": "org.cofax.SqlDataStore",
            "redirectionClass": "org.cofax.SqlRedirection",
            "dataStoreName": "cofax",
            "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
            "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
            "dataStoreUser": "sa",
            "dataStorePassword": "dataStoreTestQuery",
            "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
            "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
            "dataStoreInitConns": 10,
            "dataStoreMaxConns": 100,
            "dataStoreConnUsageLimit": 100,
            "dataStoreLogLevel": "debug",
            "maxUrlLength": 500
          }
        }, {
          "servlet-name": "cofaxEmail",
          "servlet-class": "org.cofax.cds.EmailServlet",
          "init-param": {
            "mailHost": "mail1",
            "mailHostOverride": "mail2"
          }
        }, {
          "servlet-name": "cofaxAdmin",
          "servlet-class": "org.cofax.cds.AdminServlet"
        },

        {
          "servlet-name": "fileServlet",
          "servlet-class": "org.cofax.cds.FileServlet"
        }, {
          "servlet-name": "cofaxTools",
          "servlet-class": "org.cofax.cms.CofaxToolsServlet",
          "init-param": {
            "templatePath": "toolstemplates/",
            "log": 1,
            "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
            "logMaxSize": "",
            "dataLog": 1,
            "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
            "dataLogMaxSize": "",
            "removePageCache": "/content/admin/remove?cache=pages&id=",
            "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
            "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
            "lookInContext": 1,
            "adminGroupID": 4,
            "betaServer": true
          }
        }],
        "servlet-mapping": {
          "cofaxCDS": "/",
          "cofaxEmail": "/cofaxutil/aemail/*",
          "cofaxAdmin": "/admin/*",
          "fileServlet": "/static/*",
          "cofaxTools": "/tools/*"
        },

        "taglib": {
          "taglib-uri": "cofax.tld",
          "taglib-location": "/WEB-INF/tlds/cofax.tld"
        }
      }
      };
</script>
<script>
Benchmark.prototype.setup = function() {
    scope.i = 0;
   
    scope.smallData = {
      'lastname': lastnames[Math.floor(Math.random() * 5)],
      'firstanme': firstnames[Math.floor(Math.random() * 4)],
      'dummyData': {}
    };
   
    scope.largeData = {
      'lastname': lastnames[Math.floor(Math.random() * 5)],
      'firstanme': firstnames[Math.floor(Math.random() * 4)],
      'dummyData': dummyData
    };
   
    scope.smallData.id = ++scope.i;
    ls[scope.smallData.id] = JSON.stringify(scope.smallData);
    idb.put(scope.smallData);
    websql.transaction(function(tx) {
      tx.executeSql('INSERT INTO benchmark (id, value) VALUES (?, ?)', [scope.smallData.id, JSON.stringify(scope.smallData)])
    });
   
    scope.largeData.id = ++scope.i;
    ls[scope.largeData.id] = JSON.stringify(scope.largeData);
    idb.put(scope.largeData);
    websql.transaction(function(tx) {
      tx.executeSql('INSERT INTO benchmark (id, value) VALUES (?, ?)', [scope.largeData.id, JSON.stringify(scope.largeData)])
    });
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
IDB read small data
// async test
idb.get(scope.smallData.id, function(res) {
  var value = res;
  deferred.resolve();
});
pending…
IDB read large data
// async test
idb.get(scope.largeData.id, function(res) {
  var value = res;
  deferred.resolve();
});
pending…
localStorage read small data
var value = JSON.parse(ls[scope.smallData.id]);
pending…
localStorage read large data
var value = JSON.parse(ls[scope.largeData.id]);
pending…
WebSQL read small data
// async test
websql.transaction( function(tr){
  tr.executeSql('SELECT * FROM benchmark WHERE id=?', [scope.smallData.id], function(t1, r1) {
    deferred.resolve();
  });
});
pending…
WebSQL read large data
// async test
websql.transaction( function(tr){
  tr.executeSql('SELECT * FROM benchmark WHERE id=?', [scope.largeData.id], function(t1, r1) {
    deferred.resolve();
  });
});
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment