IndexedDB vs localStorage vs WebSQL (v35)

Revision 35 of this benchmark created on


Description

This tests localStorage performance against IndexedDB, and WebSQL,all as an object store. localStorage tests contain JSON stringify/parse methods.

There's a performance penalty for the IDB tests though, as these operate on IDB via a wrapper, so there are are some additional function calls being made.

Additionally there is no JSON processing in WebSQL read, due to some errors.

Preparation HTML

<script src="https://raw.github.com/jensarps/IDBWrapper/master/IDBStore.js"></script>
<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>

Setup

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
    };

Test runner

Ready to run.

Testing in
TestOps/sec
localStorage read/write small data
scope.smallData.id = ++scope.i;
ls.setItem(scope.smallData.id, JSON.stringify(scope.smallData));
var value = JSON.parse(ls.getItem(scope.smallData.id));
ready
localStorage read/write large data
scope.largeData.id = ++scope.i;
ls.setItem(scope.largeData.id, JSON.stringify(scope.largeData));
var value = JSON.parse(ls.getItem(scope.largeData.id));
ready
IDB read/write small data
// async test
var value;
scope.smallData.id = ++scope.i;
idb.put(scope.smallData, function(res){
  idb.get(scope.smallData.id, function(res){
    value = res;
    deferred.resolve();
  });
});
ready
IDB read/write large data
// async test
var value;
scope.largeData.id = ++scope.i;
idb.put(scope.largeData, function(res){
  idb.get(scope.largeData.id, function(res){
    value = res;
    deferred.resolve();
  });
});
ready
WebSQL read/write small data
// async test
var value;
scope.smallData.id = ++scope.i;
websql.transaction(function(tx) {
  tx.executeSql('INSERT INTO benchmark (id, value) VALUES (?, ?)', [scope.smallData.id,  JSON.stringify(scope.smallData)], function(t, r){
   t.executeSql('SELECT * FROM benchmark WHERE id=?', [scope.smallData.id], function(t1,r1){

     deferred.resolve();
   });
 });
});
ready
WebSQL read/write large data
// async test
var value;
scope.largeData.id = ++scope.i;
websql.transaction(function(tx) {
  tx.executeSql('INSERT INTO benchmark (id, value) VALUES (?, ?)', [scope.largeData.id,  JSON.stringify(scope.largeData)], function(t, r){
   t.executeSql('SELECT * FROM benchmark WHERE id=?', [scope.largeData.id], function(t1,r1){
  
     deferred.resolve();
   });
 });
});
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.