77 | IndexedDB is a client side storage mechanism for storing large amounts of data with support for transactions and indexing. This github project is a list of my experiments with the IndexedDB implementation in various browsers. I have also 78 | blogged 79 | about my experiments. 80 |
81 |82 | See IndexedDB Playground » 83 |
84 | 85 |108 | The API is not 109 | supported all browsers 110 | . 111 | However, unsupported browser do implement WebSQL, another (deprecated) standard for client side storage. The IndexedDB Polyfill is an implementation of the IndexedDB API on top of the WebSQL API in Javascript. Using the polyfill, you can write IndexedDB code and run them on unsupported browsers and even on mobile devices. Try running the 112 | tests 113 | on an unsupported browser. 114 |
115 |116 | View Project » 117 |
118 |122 | The IndexedDB API seems verbose and I wanted to make it simpler to use. Here is an implementation of the API as a jquery plugin that makes using the API simpler. It uses the jquery friendly patterns like promises, method chaining, etc, to make the API easier to use. You can also look at the 123 | API documentation 124 | or an 125 | example app 126 | . The plugin also has 127 | tests 128 | that you can run to see if it works for you. 129 |
130 |131 | View Project » 132 |
133 |137 | The Performance experiments try to identify the fastest way to perform a set of operations, in various combinations. The performance experiments test some of the most common patterns when IndexedDB is used. 138 |
139 |140 | Performance Results » 141 |
142 |148 | I have also been helping other libraries that use IndexedDB libraries. Here are some of them 149 |
150 |W3Conf
169 | 170 |HTML5DevConf
175 | 176 |SFHTML5 Meetup
181 | 182 |Doctype HTML5
187 | 188 |Zeollar
193 | 194 |",
5 | "license": "BSD",
6 | "devDependencies": {
7 | "grunt-contrib-watch": "~0.3.1",
8 | "grunt-contrib-connect": "~0.2.0",
9 | "grunt": "~0.4.0",
10 | "grunt-contrib-jshint": "~0.2.0"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/perf/README.md:
--------------------------------------------------------------------------------
1 | #IndexedDB Performance Tests
2 |
3 | * Indexes
4 | * Number of Indexes
5 | * Index depths
6 | * Uniqueness
7 | * Multi Entry
8 |
9 | * Write operation
10 | * Add vs Modify
11 |
12 | * Transactions
13 | * Same transaction object, all stores
14 | * Two transctions, individual stores
15 |
16 |
17 |
18 | #DONE
19 | * Keys Compare
20 | * Strings
21 | * Numbers
22 | * Other types
23 | * Read
24 | * Read in same transaction from multiple stores
25 | * Read in different transaction per store
26 | * Write
27 | * Write in a loop
28 | * Write in a transaction loop
29 |
30 | * Table Schema
31 | * With Auto Increment
32 | * With KeyPath
33 |
34 | * Iterate
35 | * Index iteration vs primary key iteration
36 |
37 | * Read/Write
38 | * Read/Write in the same transaction
39 | * Read/Write in different transactions
40 | * Index Get
41 | * Get Indexed object
42 | * Get indexed key and then object
43 |
44 | * Cursor
45 | * Advance 1 vs Continue
46 | * Index Iterate
47 | * Key Iterator + Get Object
48 | * Object Iterator
--------------------------------------------------------------------------------
/perf/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | IndexedDB Performance Test cases
5 |
6 |
7 |
8 |
9 |
10 |
60 |
61 |
62 |
63 |
64 |
80 |
79 |
81 |
90 |
91 | IndexedDB
92 | Performance Test Scenarios
93 |
94 |
95 |
177 |
178 |
179 |
180 |
181 | View in Browserscope
182 |
183 |
184 |
185 |
186 | Results
187 |
188 |
189 |
190 |
191 |
192 |
193 |
214 |
215 |
216 |
231 | Longer graphs imply faster operations. X axis is operations per second. Uses BenchmarkJs.
232 |
233 |
234 |
220 |
224 |
229 |
230 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 | Discussion
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
89 |
257 |
258 |
259 |
260 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
--------------------------------------------------------------------------------
/perf/lib/underscore.min.js:
--------------------------------------------------------------------------------
1 | (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);
--------------------------------------------------------------------------------
/perf/main.css:
--------------------------------------------------------------------------------
1 | @media (min-width: 979px){
2 | .container-fluid {
3 | margin-top: 60px;
4 | }
5 | }
6 |
7 | .progress-active{
8 | background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)) !important;
9 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) !important;
10 | background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) !important;
11 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) !important;
12 | background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) !important;
13 | -webkit-background-size: 40px 40px;
14 | -moz-background-size: 40px 40px;
15 | -o-background-size: 40px 40px;
16 | background-size: 40px 40px;
17 | -webkit-animation: progress-bar-stripes 2s linear infinite;
18 | -moz-animation: progress-bar-stripes 2s linear infinite;
19 | -ms-animation: progress-bar-stripes 2s linear infinite;
20 | -o-animation: progress-bar-stripes 2s linear infinite;
21 | animation: progress-bar-stripes 2s linear infinite;
22 | }
23 |
24 | .accordion-group{
25 | margin-bottom : 20px;
26 | }
27 |
28 | .accordion-heading h4{
29 | background-color: #f5f5f5;
30 | margin-top: 0px;
31 | margin-bottom: 0px;
32 | }
33 |
34 | .accordion-heading a:hover{
35 | text-decoration: none;
36 | }
37 |
38 | .accordion-toggle i{
39 | margin-top: 4px;
40 | }
41 |
42 | .accordion-inner h5 a.btn{
43 | margin-left: 10px;
44 | }
45 |
46 | .controls a{
47 | margin-right: 10px;
48 | }
49 |
50 | .rank{
51 | margin-right: 10px;
52 | }
53 |
54 | .right-align {
55 | text-align: right !important;
56 | }
57 |
58 | .center-align{
59 | text-align: center !important;
60 | }
61 |
62 | .sidebar-nav{
63 | padding: 9px 0;
64 | }
65 |
66 | #idbUnsupported{
67 | text-align: center;
68 | }
69 |
70 | #disqusComments{
71 | border: none;
72 | width: 100%;
73 | }
74 |
75 | .browserscopeLink{
76 | margin: 7px;
77 | }
--------------------------------------------------------------------------------
/perf/main.js:
--------------------------------------------------------------------------------
1 | window.IndexedDBPerf = {
2 | suites: {},
3 | results: {
4 | running: false
5 | },
6 | googleLoaded: false
7 | };
8 |
9 | try {
10 | google.load('visualization', '1.0', {
11 | 'packages': ['corechart']
12 | });
13 | google.setOnLoadCallback(function() {
14 | window.IndexedDBPerf.googleLoaded = true;
15 | browserScope.loadResults();
16 | });
17 | } catch (e) {
18 |
19 | }
20 |
21 | var disqus_shortname = 'indexeddbperformance',
22 | disqus_identifier, disqus_title, disqus_url;
23 | var disqus = (function() {
24 | return {
25 | loadComments: function(currentPageId) {
26 | // http://docs.disqus.com/help/2/
27 | window.disqus_shortname = 'indexeddbperformance';
28 | window.disqus_identifier = currentPageId;
29 | window.disqus_url = 'http://nparashuram.com/IndexedDB/perf/' + currentPageId;
30 |
31 | // http://docs.disqus.com/developers/universal/
32 | (function() {
33 | var dsq = document.createElement('script');
34 | dsq.type = 'text/javascript';
35 | dsq.async = true;
36 | dsq.src = 'http://indexeddbperformance.disqus.com/embed.js';
37 | (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
38 | dsq.onload = function() {
39 | dsq.parentNode.removeChild(dsq)
40 | }
41 | })();
42 | }
43 | }
44 | }());
45 |
46 | var browserScope = (function() {
47 | var currentTest = null;
48 | return {
49 | saveResults: function() {
50 | $('.browserScope .alert').hide();
51 | if (typeof currentTest === 'undefined' || typeof window.IndexedDBPerf.suites[currentTest] === 'undefined' || window.IndexedDBPerf.suites[currentTest]._bTestKey === 'undefined') {
52 | $('.browserScope .saveError').fadeIn();
53 | }
54 | window._bTestResults = {};
55 | _.each(window.IndexedDBPerf.results, function(o) {
56 | // Hate losing the prescision here
57 | window._bTestResults[o.name.replace(/[,]/g, " ")] = (o.hz * 1000).toFixed(0);
58 | });
59 | var url = ['http://www.browserscope.org/user/beacon/', window.IndexedDBPerf.suites[currentTest]._bTestKey];
60 | $.getScript(url.join(''), function() {
61 | $('.browserScope .saveDone').fadeIn();
62 | });
63 | },
64 | loadResults: function(testName) {
65 | $('.browserScope .alert').hide();
66 | $('#viz').html('Loading');
67 | testName && (currentTest = testName);
68 | if (window.IndexedDBPerf.googleLoaded === false) return;
69 | if (typeof window.IndexedDBPerf.suites[currentTest] === 'undefined' || typeof window.IndexedDBPerf.suites[currentTest]._bTestKey === 'undefined') {
70 | $('#viz').empty();
71 | $('.browserScope .loadError').fadeIn();
72 | return;
73 | }
74 | $('.browserscopeLink').attr('href', 'http://www.browserscope.org/user/tests/table/' + window.IndexedDBPerf.suites[currentTest]._bTestKey);
75 | $.getJSON('http://www.browserscope.org/user/tests/table/' + window.IndexedDBPerf.suites[currentTest]._bTestKey + '?v=0&o=json&callback=?', function(res, status) {
76 | if (status !== 'success') {
77 | $('.browserScope .loadError').fadeIn();
78 | return;
79 | }
80 | var data = new google.visualization.DataTable();
81 | data.addColumn('string', 'Browser');
82 | var headerAdded = false;
83 | _.each(res.results, function(o, key) {
84 | if (!headerAdded) {
85 | _.each(o.results, function(v, k) {
86 | data.addColumn('number', k);
87 | });
88 | headerAdded = true;
89 | }
90 | if (o.count > 0) {
91 | data.addRow([key].concat(_.map(o.results, function(x) {
92 | return parseFloat(x.result/1000);
93 | })));
94 | }
95 | });
96 |
97 | var chart = new google.visualization.BarChart(document.getElementById('viz'));
98 | chart.draw(data, {
99 | height: 500,
100 | animation: {
101 | duration: 500,
102 | easing: 'inAndOut'
103 | },
104 | legend: {
105 | position: 'top'
106 | }
107 | });
108 | });
109 | }
110 | }
111 | }());
112 |
113 | $(document).ready(function() {
114 | if (typeof window.indexedDB === 'undefined') {
115 | $('#idbUnsupported').show();
116 | }
117 |
118 | var el = $("#perfTestLinks");
119 | var content = $("#testContent");
120 | var contentTemplate = _.template(content.next("script[type='text/html']").text());
121 | var resultsTemplate = _.template($('.resultsContent').children('script[type="text/html"]').text());
122 |
123 | el.html(_.template(el.text())({
124 | perf: window.IndexedDBPerf.suites
125 | }))
126 |
127 | el.on("click", "li>a", function() {
128 | el.children("li").removeClass("active");
129 | var $this = $(this);
130 | $this.parent().addClass("active");
131 | content.html(contentTemplate($.extend({
132 | "name": $this.data("name"),
133 | "desc": "",
134 | "onStart": "",
135 | "setup": "",
136 | "tearDown": "",
137 | tests: []
138 | }, window.IndexedDBPerf.suites[$this.data("name")])));
139 | content.find('pre').each(function() {
140 | var $this = $(this);
141 | $this.html(js_beautify($this.html()));
142 | });
143 |
144 | $('.resultsContent').hide();
145 | browserScope.loadResults($this.data('name'));
146 | disqus.loadComments($this.data('name'));
147 | });
148 |
149 | $(document).on('click', '.runTestCase', function() {
150 | var $this = $(this);
151 | window.IndexedDBPerf.suites[$this.data('suite')].tests[$this.data('name')]({
152 | resolve: function() {
153 | alert("Ran " + $this.data('suite') + ":" + $this.data("name"));
154 | }
155 | })
156 | });
157 |
158 | $(document).on('click', '.runPreTest', function() {
159 | var $this = $(this);
160 | window.IndexedDBPerf.suites[$this.data('suite')][$this.data('name')]($.noop, $.noop);
161 | });
162 |
163 | $(document).on('click', '.abortTests', function() {
164 | if (window.IndexedDBPerf.results.running) {
165 | return;
166 | }
167 | if (confirm("Are you sure you want to abort the tests ? ")) {
168 | window.IndexedDBPerf.results.abort();
169 | $('.runTests').show();
170 | $('.abortTests').hide();
171 | }
172 | });
173 |
174 | $(document).on('click', '.runTests', function() {
175 | if (window.IndexedDBPerf.results.running) {
176 | return;
177 | }
178 |
179 | $('.runTests').hide();
180 | $('.abortTests').show();
181 |
182 | var progress = $(".progress").show();
183 | progress.children().width(0).empty();
184 | progress.children('.start').width('3%');
185 | progress.children('.tests');
186 | bar = progress.children('.pretest').width('7%').addClass('progress-active');
187 | var cycle = 0,
188 | suite = window.IndexedDBPerf.suites[$(this).data("name")],
189 | testWidth = (80 / _.size(suite.tests)) + "%";
190 | suite.onStart(function() {
191 | var bm = new Benchmark.Suite;
192 | window.IndexedDBPerf.results = bm;
193 | for (var test in suite.tests) {
194 | bm.add({
195 | name: test,
196 | fn: suite.tests[test],
197 | setup: suite.setup,
198 | teardown: suite.teardown,
199 | onStart: function() {
200 | bar = progress.children(".tests[data-name='" + this.name + "']").width(testWidth).addClass('progress-active bar-success');
201 | cycle = 0;
202 | },
203 | onComplete: function() {
204 | bar.removeClass('progress-active');
205 | },
206 | onCycle: function() {
207 | bar.html('' + cycle+++'');
208 | },
209 | defer: typeof suite.defer === 'undefined' ? true : suite.defer
210 | });
211 | }
212 | bm.on('complete', function() {
213 | progress.children('.done').width('10%');
214 | $('.runTests').show();
215 | $('.abortTests').hide();
216 | $('.resultsContent').hide();
217 | $(".resultsContent").html(resultsTemplate({
218 | bm: this
219 | })).show();
220 | $('.rank').removeClass('badge-important badge-warning badge-success');
221 | _.each(_.sortBy(this, 'hz'), function(c, i, array) {
222 | var best = array[array.length - 1].hz;
223 | $(".percentSlow[data-name='" + c.name + "']").html(((best - c.hz) / best * 100).toFixed(2));
224 | $(".rank[data-name='" + c.name + "']").html(array.length - i).show().addClass(function() {
225 | switch (i) {
226 | case 0:
227 | return 'badge-important';
228 | case array.length - 1:
229 | return 'badge-success';
230 | default:
231 | return 'badge-warning';
232 | }
233 | }).attr("title", c.hz);
234 | });
235 | browserScope.saveResults();
236 | });
237 |
238 | bm.on('abort', function() {
239 | progress.children(".tests").width(testWidth);
240 | });
241 |
242 | bm.run({
243 | 'async': true
244 | });
245 | progress.children('.pretest').removeClass('progress-active')
246 | }, function(num) {
247 | bar.html('' + cycle+++'');
248 | });
249 | });
250 |
251 | var hash = unescape(document.location.hash.substring(1));
252 | el.children(hash ? "li[data-name='" + hash + "']" : "li:not('.nav-header'):first").children("a").click();
253 | });
--------------------------------------------------------------------------------
/perf/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
81 |
82 |
--------------------------------------------------------------------------------
/perf/tests/10_TransactionReadWriteIsolation.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Read and Write transaction isolation'] = {
3 | category :'Transaction',
4 | desc : 'Should read and write operations be in the same transction, or be in different transactions',
5 | _bTestKey:'agt1YS1wcm9maWxlcnINCxIEVGVzdBiJ8KIUDA',
6 | onStart: function(cb, status) {
7 | window.MAX = 1000;
8 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
9 | $.indexedDB('IndexedDBPerf', {
10 | schema: {
11 | 1: function(transaction) {
12 | var table1 = transaction.createObjectStore("Table1", {
13 | 'autoIncrement': true
14 | });
15 | var table2 = transaction.createObjectStore("Table2", {
16 | 'autoIncrement': true
17 | });
18 | var table3 = transaction.createObjectStore("Table3", {
19 | 'autoIncrement': true
20 | });
21 | var table4 = transaction.createObjectStore("Table4", {
22 | 'autoIncrement': true
23 | });
24 | }
25 | }
26 | }).done(function() {
27 | var table1 = $.indexedDB('IndexedDBPerf').objectStore('Table1');
28 | var table2 = $.indexedDB('IndexedDBPerf').objectStore('Table2');
29 | var table3 = $.indexedDB('IndexedDBPerf').objectStore('Table3');
30 | var table4 = $.indexedDB('IndexedDBPerf').objectStore('Table4');
31 | var added = 0;
32 |
33 | function done() {
34 | if (++added >= MAX * 4) {
35 | cb();
36 | }
37 | status();
38 | }
39 | for (var i = 0; i < MAX; i++) {
40 | table1.add(Faker.Helpers.createCard()).always(done);
41 | table2.add(Faker.Helpers.createCard()).always(done);
42 | table3.add(Faker.Helpers.createCard()).always(done);
43 | table4.add(Faker.Helpers.createCard()).always(done);
44 | }
45 | });
46 | });
47 | },
48 | setup: function() {
49 | window.data = Faker.Helpers.createCard();
50 | },
51 | teardown: function() {
52 |
53 | },
54 | tests: {
55 | 'Same transaction, READ first': function(deferred) {
56 | var req = window.indexedDB.open('IndexedDBPerf');
57 | var readCount = 0,
58 | writeCount = 0;
59 | req.onsuccess = function() {
60 | var db = req.result;
61 | var transaction = db.transaction(['Table2'], 'readwrite');
62 | var objStore = transaction.objectStore('Table2');
63 | for (var i = 0; i < MAX; i++) {
64 | (function() {
65 | var readReq = objStore.get(i);
66 | readReq.onsuccess = function() {
67 | if (++readCount >= MAX && writeCount >= MAX) {
68 | db.close();
69 | deferred.resolve();
70 | }
71 | };
72 | readReq.onerror = function(e) {
73 | throw e;
74 | }
75 | }(i));
76 | }
77 | for (var i = MAX; i < MAX * 2; i++) {
78 | (function() {
79 | var writeReq = objStore.put(window.data, i);
80 | writeReq.onsuccess = function() {
81 | if (++writeCount >= MAX && readCount >= MAX) {
82 | db.close();
83 | deferred.resolve();
84 | }
85 | };
86 | writeReq.onerror = function(e) {
87 | throw e;
88 | }
89 | }(i));
90 | }
91 | };
92 | req.onerror = function() {
93 | throw "Could not open database";
94 | };
95 | },
96 | 'Same transaction WRITE first': function(deferred) {
97 | var req = window.indexedDB.open('IndexedDBPerf');
98 | var readCount = 0,
99 | writeCount = 0;
100 | req.onsuccess = function() {
101 | var db = req.result;
102 | var transaction = db.transaction(['Table1'], 'readwrite');
103 | var objStore = transaction.objectStore('Table1');
104 | for (var i = MAX; i < MAX * 2; i++) {
105 | (function() {
106 | var writeReq = objStore.put(window.data, i);
107 | writeReq.onsuccess = function() {
108 | if (++writeCount >= MAX && readCount >= MAX) {
109 | db.close();
110 | deferred.resolve();
111 | }
112 | };
113 | writeReq.onerror = function(e) {
114 | throw e;
115 | }
116 | }(i));
117 | }
118 | for (var i = 0; i < MAX; i++) {
119 | (function() {
120 | var readReq = objStore.get(i);
121 | readReq.onsuccess = function() {
122 | if (writeCount >= MAX && ++readCount >= MAX) {
123 | db.close();
124 | deferred.resolve();
125 | }
126 | };
127 | readReq.onerror = function(e) {
128 | throw e;
129 | }
130 | }(i));
131 | }
132 | };
133 | req.onerror = function() {
134 | throw "Could not open database";
135 | };
136 | },
137 | 'Separate transactions, Write first': function(deferred) {
138 | var req = window.indexedDB.open('IndexedDBPerf');
139 | var readCount = 0,
140 | writeCount = 0;
141 | req.onsuccess = function() {
142 | var db = req.result;
143 | var transaction1 = db.transaction(['Table3'], 'readwrite');
144 | var objStore1 = transaction1.objectStore('Table3');
145 | for (var i = MAX; i < MAX * 2; i++) {
146 | (function() {
147 | var writeReq = objStore1.put(window.data, i);
148 | writeReq.onsuccess = function() {
149 | if (++writeCount >= MAX && readCount >= MAX) {
150 | db.close();
151 | deferred.resolve();
152 | }
153 | };
154 | writeReq.onerror = function(e) {
155 | throw e;
156 | }
157 | }(i));
158 | }
159 | var transaction2 = db.transaction(['Table3'], 'readonly');
160 | var objStore2 = transaction2.objectStore('Table3');
161 | for (var i = 0; i < MAX; i++) {
162 | (function() {
163 | var readReq = objStore2.get(i);
164 | readReq.onsuccess = function() {
165 | if (writeCount >= MAX && ++readCount >= MAX) {
166 | db.close();
167 | deferred.resolve();
168 | }
169 | };
170 | readReq.onerror = function(e) {
171 | throw e;
172 | }
173 | }(i));
174 | }
175 | };
176 | req.onerror = function() {
177 | throw "Could not open database";
178 | };
179 | },
180 | 'Separate Transactions, Read first': function(deferred) {
181 | var req = window.indexedDB.open('IndexedDBPerf');
182 | var readCount = 0,
183 | writeCount = 0;
184 | req.onsuccess = function() {
185 | var db = req.result;
186 | var transaction2 = db.transaction(['Table4'], 'readonly');
187 | var objStore2 = transaction2.objectStore('Table4');
188 | for (var i = 0; i < MAX; i++) {
189 | (function() {
190 | var readReq = objStore2.get(i);
191 | readReq.onsuccess = function() {
192 | if (++readCount >= MAX && writeCount >= MAX) {
193 | db.close();
194 | deferred.resolve();
195 | }
196 | };
197 | readReq.onerror = function(e) {
198 | throw e;
199 | }
200 | }(i));
201 | }
202 | var transaction1 = db.transaction(['Table4'], 'readwrite');
203 | var objStore1 = transaction1.objectStore('Table4');
204 | for (var i = MAX; i < MAX * 2; i++) {
205 | (function() {
206 | var writeReq = objStore1.put(window.data, i);
207 | writeReq.onsuccess = function() {
208 | if (++writeCount >= MAX && readCount >= MAX) {
209 | db.close();
210 | deferred.resolve();
211 | }
212 | };
213 | writeReq.onerror = function(e) {
214 | throw e;
215 | }
216 | }(i));
217 | }
218 | };
219 | req.onerror = function() {
220 | throw "Could not open database";
221 | };
222 | }
223 | }
224 | };
225 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/11_IndexKeyObjectCursor.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Key and Object Cursor on Index'] = {
3 | category: 'Indexes',
4 | desc: "What is faster - A key cursor on an Index, or an object cursor on an index",
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBj26aEUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | schema: {
10 | 1: function(transaction) {
11 | var table1 = transaction.createObjectStore("Table1", {
12 | 'autoIncrement': true
13 | });
14 | table1.createIndex("username", {
15 | 'unique': false
16 | });
17 | }
18 | }
19 | }).done(function() {
20 | var objStore = $.indexedDB('IndexedDBPerf').objectStore('Table1');
21 | var added = 0;
22 | for (var i = 0; i < 1000; i++) {
23 | objStore.add(Faker.Helpers.createCard()).always(function() {
24 | if (++added >= 999) {
25 | cb();
26 | }
27 | status();
28 | });
29 | }
30 | });
31 | });
32 | },
33 | setup: function() {},
34 | teardown: function() {},
35 | tests: {
36 | 'Key Cursors': function(deferred) {
37 | var req = window.indexedDB.open('IndexedDBPerf');
38 | var readCount = 0;
39 | req.onsuccess = function() {
40 | var db = req.result;
41 | var transaction = db.transaction(['Table1'], 'readonly');
42 | var objStore = transaction.objectStore('Table1');
43 | var index = objStore.index("username");
44 | var cursorReq = index.openKeyCursor();
45 | cursorReq.onsuccess = function() {
46 | if (cursorReq.result) {
47 | ++readCount;
48 | cursorReq.result['continue']();
49 | } else {
50 | if (readCount < 1000) {
51 | throw "Did not read all values";
52 | }
53 | db.close();
54 | deferred.resolve();
55 | }
56 |
57 | };
58 | cursorReq.onerror = function(e) {
59 | throw e;
60 | };
61 | };
62 | req.onerror = function() {
63 | throw "Could not open database";
64 | }
65 | },
66 | 'Object Cursor': function(deferred) {
67 | var req = window.indexedDB.open('IndexedDBPerf');
68 | var readCount = 0;
69 | req.onsuccess = function() {
70 | var db = req.result;
71 | var transaction = db.transaction(['Table1'], 'readonly');
72 | var objStore = transaction.objectStore('Table1');
73 | var index = objStore.index("username");
74 | var cursorReq = index.openCursor();
75 | cursorReq.onsuccess = function() {
76 | if (cursorReq.result) {
77 | ++readCount;
78 | cursorReq.result['continue']();
79 | } else {
80 | if (readCount < 1000) {
81 | throw "Did not read all values";
82 | }
83 | db.close();
84 | deferred.resolve();
85 | }
86 |
87 | };
88 | cursorReq.onerror = function(e) {
89 | throw e;
90 | };
91 | };
92 | req.onerror = function() {
93 | throw "Could not open database";
94 | }
95 | },
96 | 'Key Cursor and then Object': function(deferred) {
97 | var req = window.indexedDB.open('IndexedDBPerf');
98 | var readCount = 0;
99 | req.onsuccess = function() {
100 | var db = req.result;
101 | var transaction = db.transaction(['Table1'], 'readonly');
102 | var objStore = transaction.objectStore('Table1');
103 | var index = objStore.index("username");
104 | var cursorReq = index.openKeyCursor();
105 | cursorReq.onsuccess = function() {
106 | if (cursorReq.result) {
107 | var readReq = objStore.get(cursorReq.result.key);
108 | readReq.onsuccess = function() {
109 | if (++readCount >= 1000) {
110 | db.close();
111 | deferred.resolve();
112 | }
113 | };
114 | cursorReq.result['continue']();
115 | }
116 | };
117 | cursorReq.onerror = function(e) {
118 | throw e;
119 | };
120 | };
121 | req.onerror = function() {
122 | throw "Could not open database";
123 | }
124 | }
125 | }
126 | };
127 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/12_CursorContinueAdvance.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Cursor Advance/Continue'] = {
3 | category: 'Cursors',
4 | desc: "What is faster - advancing in a cursor, or just calling continue",
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBjSvaMUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | schema: {
10 | 1: function(transaction) {
11 | var table1 = transaction.createObjectStore("Table1", {
12 | 'autoIncrement': true
13 | });
14 | table1.createIndex("username", {
15 | 'unique': false
16 | });
17 | }
18 | }
19 | }).done(function() {
20 | var objStore = $.indexedDB('IndexedDBPerf').objectStore('Table1');
21 | var added = 0;
22 | for (var i = 0; i < 1000; i++) {
23 | objStore.add(Faker.Helpers.createCard()).always(function() {
24 | if (++added >= 999) {
25 | cb();
26 | }
27 | status();
28 | });
29 | }
30 | });
31 | });
32 | },
33 | setup: function() {},
34 | teardown: function() {},
35 | tests: {
36 | 'Cursor Continue': function(deferred) {
37 | var req = window.indexedDB.open('IndexedDBPerf');
38 | var readCount = 0;
39 | req.onsuccess = function() {
40 | var db = req.result;
41 | var transaction = db.transaction(['Table1'], 'readonly');
42 | var objStore = transaction.objectStore('Table1');
43 | var cursorReq = objStore.openCursor(IDBKeyRange.bound(0, 1000, true, true), "next");
44 | cursorReq.onsuccess = function() {
45 | if (cursorReq.result) {
46 | var data = cursorReq.result.value;
47 | readCount++;
48 | cursorReq.result["continue"]();
49 | } else {
50 | //console.log("All Done");
51 | if (readCount < 999) {
52 | throw "Did not read all the data" + readCount;
53 | }
54 | db.close();
55 | deferred.resolve();
56 | }
57 | };
58 | cursorReq.onerror = function() {
59 | throw "Could not create Cursor request"
60 | }
61 | };
62 | req.onerror = function() {
63 | throw "Could not open database";
64 | };
65 | },
66 | 'Cursor Advance': function(deferred) {
67 | var req = window.indexedDB.open('IndexedDBPerf');
68 | var readCount = 0;
69 | req.onsuccess = function() {
70 | var db = req.result;
71 | var transaction = db.transaction(['Table1'], 'readonly');
72 | var objStore = transaction.objectStore('Table1');
73 | var cursorReq = objStore.openCursor(IDBKeyRange.bound(0, 1000, true, true), "next");
74 | cursorReq.onsuccess = function() {
75 | if (cursorReq.result) {
76 | var data = cursorReq.result.value;
77 | readCount++;
78 | cursorReq.result["advance"](1);
79 | } else {
80 | //console.log("All Done");
81 | if (readCount < 999) {
82 | throw "Did not read all the data" + readCount;
83 | }
84 | db.close();
85 | deferred.resolve();
86 | }
87 | };
88 | cursorReq.onerror = function() {
89 | throw "Could not create Cursor request"
90 | }
91 | };
92 | req.onerror = function() {
93 | throw "Could not open database";
94 | };
95 | }
96 | }
97 | };
98 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/13_OpenDBVersions.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Open Database with version'] = {
3 | category: 'General',
4 | desc: 'Is it faster to open a database with a specified version, or should the version be omitted',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBiMm6QUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf1').deleteDatabase().done(function() {
9 | cb();
10 | });
11 | });
12 | },
13 | setup: function() {
14 | window.version = 1;
15 | },
16 | teardown: function() {},
17 | tests: {
18 | 'Open database without version': function(deferred) {
19 | var openReq = window.indexedDB.open('IndexedDBPerf');
20 | openReq.onsuccess = function() {
21 | openReq.result.close();
22 | deferred.resolve();
23 | };
24 | },
25 | 'Open database with version': function(deferred) {
26 | var openReq = window.indexedDB.open('IndexedDBPerf1', 1);
27 | openReq.onsuccess = function() {
28 | openReq.result.close();
29 | deferred.resolve();
30 | }
31 | }
32 | }
33 | };
34 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/14_TransactionObjectStore.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Objectstore per transaction'] = {
3 | category: 'ObjectStore',
4 | desc: 'Which transaction opens faster - one with all object stores, or the one per object store ? ',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBiD0LIUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | status();
9 | $.indexedDB('IndexedDBPerf', {
10 | 'schema': {
11 | 1: function(t) {
12 | for (var i = 0; i < 20; i++)
13 | t.createObjectStore('Table' + i);
14 | status();
15 | }
16 | }
17 | }).done(function() {
18 | cb();
19 | });
20 | });
21 | },
22 | setup: function() {},
23 | teardown: function() {},
24 | tests: {
25 | '1 read transaction per store': function(deferred) {
26 | var openReq = window.indexedDB.open('IndexedDBPerf');
27 | openReq.onsuccess = function() {
28 | var db = openReq.result;
29 | for (var i = 0; i < 20; i++) {
30 | db.transaction(['Table' + i], 'readonly').objectStore('Table' + i);
31 | }
32 | db.close();
33 | deferred.resolve();
34 | }
35 | },
36 | 'All stores in 1 read transaction': function(deferred) {
37 | var openReq = window.indexedDB.open('IndexedDBPerf');
38 | openReq.onsuccess = function() {
39 | var db = openReq.result;
40 | var tables = [];
41 | for (var i = 0; i < 20; i++) {
42 | tables.push('Table' + i);
43 | }
44 | var transaction = db.transaction(tables, 'readonly');
45 | for (var i = 0; i < 20; i++) {
46 | transaction.objectStore('Table' + i);
47 | }
48 | db.close();
49 | deferred.resolve();
50 | }
51 | },
52 | '1 write transaction per store': function(deferred) {
53 | var openReq = window.indexedDB.open('IndexedDBPerf');
54 | openReq.onsuccess = function() {
55 | var db = openReq.result;
56 | for (var i = 0; i < 20; i++) {
57 | db.transaction(['Table' + i], 'readwrite').objectStore('Table' + i);
58 | }
59 | db.close();
60 | deferred.resolve();
61 | }
62 | },
63 | 'All stores in 1 write transaction': function(deferred) {
64 | var openReq = window.indexedDB.open('IndexedDBPerf');
65 | openReq.onsuccess = function() {
66 | var db = openReq.result;
67 | var tables = [];
68 | for (var i = 0; i < 20; i++) {
69 | tables.push('Table' + i);
70 | }
71 | var transaction = db.transaction(tables, 'readwrite');
72 | for (var i = 0; i < 20; i++) {
73 | transaction.objectStore('Table' + i);
74 | }
75 | db.close();
76 | deferred.resolve();
77 | }
78 | }
79 | }
80 | };
81 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/15_TransactionRead.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Read Operation for per store transactions'] = {
3 | category: 'ObjectStore',
4 | desc: 'Does it matter if a read operation is performed for different object stores in different transactions, or will doing it in the same transaction be equally fast? ',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBiT9K4UDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | 'schema': {
10 | '1': function(trans) {
11 | trans.createObjectStore('Table1', {
12 | 'autoIncrement': false
13 | });
14 | trans.createObjectStore('Table2', {
15 | 'autoIncrement': false
16 | });
17 | status();
18 | }
19 | }
20 | }).done(function() {
21 | var objStore1 = $.indexedDB('IndexedDBPerf').objectStore('Table1');
22 | var objStore2 = $.indexedDB('IndexedDBPerf').objectStore('Table2');
23 | var added = 0;
24 | for (var i = 0; i < 1000; i++) {
25 | objStore1.add(Faker.Helpers.createCard(), i).always(function() {
26 | if (++added >= 1999) {
27 | cb();
28 | }
29 | status();
30 | });
31 | objStore2.add(Faker.Helpers.createCard(), i).always(function() {
32 | if (++added >= 1999) {
33 | cb();
34 | }
35 | status();
36 | });
37 | }
38 | });
39 | });
40 | },
41 | setup: function() {},
42 | teardown: function() {},
43 | defer: true,
44 | tests: {
45 | 'Read Transaction per ObjectStore': function(deferred) {
46 | var openReq = window.indexedDB.open('IndexedDBPerf');
47 | var readCount = 0;
48 | openReq.onsuccess = function() {
49 | var db = openReq.result;
50 | var objectStore1 = db.transaction(['Table1'], 'readonly').objectStore('Table1');
51 | var objectStore2 = db.transaction(['Table2'], 'readonly').objectStore('Table2');
52 | for (var i = 0; i < 1000; i++) {
53 | (function(i) {
54 | var readReq1 = objectStore1.get(i);
55 | readReq1.onsuccess = function() {
56 | if (++readCount >= 1999) {
57 | db.close();
58 | deferred.resolve();
59 | }
60 | }
61 | var readReq2 = objectStore2.get(i);
62 | readReq2.onsuccess = function() {
63 | if (++readCount >= 1999) {
64 | db.close();
65 | deferred.resolve();
66 | }
67 | }
68 | }(i));
69 | }
70 | }
71 | },
72 | 'All ObjectStore reads in a transaction': function(deferred) {
73 | var openReq = window.indexedDB.open('IndexedDBPerf');
74 | var readCount = 0;
75 | openReq.onsuccess = function() {
76 | var db = openReq.result;
77 | var transaction = db.transaction(['Table1', 'Table2'], 'readonly');
78 | var objectStore1 = transaction.objectStore('Table1');
79 | var objectStore2 = transaction.objectStore('Table2');
80 | for (var i = 0; i < 1000; i++) {
81 | (function(i) {
82 | var readReq1 = objectStore1.get(i);
83 | readReq1.onsuccess = function() {
84 | if (++readCount >= 1999) {
85 | db.close();
86 | deferred.resolve();
87 | }
88 | }
89 | var readReq2 = objectStore2.get(i);
90 | readReq2.onsuccess = function() {
91 | if (++readCount >= 1999) {
92 | db.close();
93 | deferred.resolve();
94 | }
95 | }
96 | }(i));
97 | }
98 | }
99 | }
100 | }
101 | }
102 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/16_TransactionWrite.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Write Operation for per store transactions'] = {
3 | category: 'ObjectStore',
4 | desc: 'Does it matter if a write operation is performed for different object stores in different transactions, or will doing it in the same transaction be equally fast? ',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBi_oq8UDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | 'schema': {
10 | '1': function(trans) {
11 | trans.createObjectStore('Table1', {
12 | 'autoIncrement': true
13 | });
14 | trans.createObjectStore('Table2', {
15 | 'autoIncrement': true
16 | });
17 | trans.createObjectStore('Table3', {
18 | 'autoIncrement': true
19 | });
20 | trans.createObjectStore('Table4', {
21 | 'autoIncrement': true
22 | });
23 | status();
24 | }
25 | }
26 | }).done(function() {
27 | cb();
28 | });
29 | });
30 | },
31 | setup: function() {
32 | window.data = Faker.Helpers.createCard();
33 | },
34 | teardown: function() {},
35 | defer: true,
36 | tests: {
37 | 'Write Transaction per ObjectStore': function(deferred) {
38 | var openReq = window.indexedDB.open('IndexedDBPerf');
39 | var count = 0;
40 | openReq.onsuccess = function() {
41 | var db = openReq.result;
42 | var objectStore1 = db.transaction(['Table1'], 'readwrite').objectStore('Table1');
43 | var objectStore2 = db.transaction(['Table2'], 'readwrite').objectStore('Table2');
44 | for (var i = 0; i < 1000; i++) {
45 | (function(i) {
46 | var writeReq1 = objectStore1.add(data);
47 | writeReq1.onsuccess = function() {
48 | if (++count >= 1999) {
49 | db.close();
50 | deferred.resolve();
51 | }
52 | };
53 | writeReq1.onerror = function(e) {
54 | console.log(writeReq1.error);
55 | }
56 | var writeReq2 = objectStore2.add(data);
57 | writeReq2.onsuccess = function() {
58 | if (++count >= 1999) {
59 | db.close();
60 | deferred.resolve();
61 | }
62 | }
63 | }(i));
64 | }
65 | }
66 | },
67 | 'All ObjectStore write in a transaction': function(deferred) {
68 | var openReq = window.indexedDB.open('IndexedDBPerf');
69 | var count = 0;
70 | openReq.onsuccess = function() {
71 | var db = openReq.result;
72 | var transaction = db.transaction(['Table3', 'Table4'], 'readwrite');
73 | var objectStore1 = transaction.objectStore('Table3');
74 | var objectStore2 = transaction.objectStore('Table4');
75 | for (var i = 0; i < 1000; i++) {
76 | (function(i) {
77 | var writeReq1 = objectStore1.add(data);
78 | writeReq1.onsuccess = function() {
79 | if (++count >= 1999) {
80 | db.close();
81 | deferred.resolve();
82 | }
83 | }
84 | var writeReq2 = objectStore2.add(data);
85 | writeReq2.onsuccess = function() {
86 | if (++count >= 1999) {
87 | db.close();
88 | deferred.resolve();
89 | }
90 | }
91 | }(i));
92 | }
93 | }
94 | }
95 | }
96 | }
97 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/17_AddUpdate.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Add and Update'] = {
3 | desc: 'Is it better to insert data using add call or update call',
4 | category: 'ObjectStore',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBio8aoUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | 'schema': {
10 | '1': function(trans) {
11 | trans.createObjectStore('Table1', {
12 | 'autoIncrement': true
13 | });
14 | trans.createObjectStore('Table2', {
15 | 'autoIncrement': true
16 | });
17 | status();
18 | }
19 | }
20 | }).done(function() {
21 | cb();
22 | });
23 | });
24 | },
25 | setup: function() {
26 | window.data = Faker.Helpers.createCard();
27 | },
28 | teardown: function() {},
29 | defer: true,
30 | tests: {
31 | 'Write using Add': function(deferred) {
32 | var openReq = window.indexedDB.open('IndexedDBPerf');
33 | var count = 0;
34 | openReq.onsuccess = function() {
35 | var db = openReq.result;
36 | var objectStore = db.transaction(['Table1'], 'readwrite').objectStore('Table1');
37 | for (var i = 0; i < 1000; i++) {
38 | (function(i) {
39 | var writeReq = objectStore.add(data);
40 | writeReq.onsuccess = function() {
41 | if (++count >= 999) {
42 | db.close();
43 | deferred.resolve();
44 | }
45 | };
46 | }(i));
47 | }
48 | }
49 | },
50 | 'Write using Put': function(deferred) {
51 | var openReq = window.indexedDB.open('IndexedDBPerf');
52 | var count = 0;
53 | openReq.onsuccess = function() {
54 | var db = openReq.result;
55 | var objectStore = db.transaction(['Table2'], 'readwrite').objectStore('Table2');
56 | for (var i = 0; i < 1000; i++) {
57 | (function(i) {
58 | var writeReq = objectStore.put(data);
59 | writeReq.onsuccess = function() {
60 | if (++count >= 999) {
61 | db.close();
62 | deferred.resolve();
63 | }
64 | };
65 | }(i));
66 | }
67 | }
68 | }
69 | }
70 | };
71 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/1_KeyCompare.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Comparing Keys'] = {
3 | category: 'General',
4 | desc: 'Performance for comparing different key types',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBir36IUDA',
6 | onStart: function(cb) {
7 | cb();
8 | },
9 | setup: function() {
10 | window.str1 = Faker.Lorem.sentence();
11 | window.str2 = Faker.Lorem.sentence();
12 | window.long1 = Math.random();
13 | window.long2 = Math.random();
14 | window.num1 = Faker.Helpers.randomNumber(10000);
15 | window.num2 = Faker.Helpers.randomNumber(10000);
16 | window.ar1 = Faker.Lorem.sentences().split(" ");
17 | window.ar2 = Faker.Lorem.sentences().split(" ");
18 | window.nar1 = Faker.Lorem.sentences().split(" ");
19 | nar1.push(Faker.Lorem.sentences().split(" "));
20 | nar1.push(Faker.Lorem.sentences().split(" "));
21 | nar1.push(Faker.Lorem.sentences().split(" "));
22 | window.nar2 = Faker.Lorem.sentences().split(" ");
23 | nar2.push(Faker.Lorem.sentences().split(" "));
24 | nar2.push(Faker.Lorem.sentences().split(" "));
25 | nar2.push(Faker.Lorem.sentences().split(" "));
26 | },
27 | teardown: function() {
28 |
29 | },
30 | defer : false,
31 | tests: {
32 | 'Integers': function(deferred) {
33 | window.indexedDB.cmp(num1, num2);
34 | },
35 | 'Longs': function() {
36 | window.indexedDB.cmp(long1, long2);
37 | },
38 | 'String': function() {
39 | window.indexedDB.cmp(str1, str2);
40 | },
41 | 'Arrays': function() {
42 | window.indexedDB.cmp(ar1, ar2);
43 | },
44 | 'Nested Arrays': function() {
45 | window.indexedDB.cmp(nar1, nar2);
46 | }
47 | }
48 | };
49 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/2_TableSchema_Write.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Table Schema Write'] = {
3 | category : 'ObjectStore',
4 | desc : 'Is it faster to queue up write requests in a single transaction, or start multiple transactions with with writes requests batched in them',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBjt9acUDA',
6 | onStart: function(cb) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | schema: {
10 | 1: function(transaction) {
11 | var table1 = transaction.createObjectStore("Table1", {
12 | 'autoIncrement': false
13 | });
14 |
15 | var table2 = transaction.createObjectStore("Table2", {
16 | 'keyPath': 'id',
17 | 'autoIncrement': true
18 | });
19 | var table3 = transaction.createObjectStore("Table3", {
20 | 'keyPath': 'id',
21 | 'autoIncrement': false
22 | });
23 |
24 | var table4 = transaction.createObjectStore("Table4", {
25 | 'autoIncrement': true
26 | });
27 |
28 | var table5 = transaction.createObjectStore("Table5", {
29 | 'autoIncrement': true
30 | });
31 | table5.createIndex("name");
32 | table5.createIndex("username");
33 | }
34 | }
35 | }).done(function() {
36 | cb();
37 | });
38 | });
39 | },
40 | setup: function() {
41 | var data = Faker.Helpers.createCard();
42 | window.key++;
43 |
44 | function err() {
45 | console.log.apply(console, arguments);
46 | }
47 | },
48 | teardown: function() {
49 |
50 | },
51 | tests: {
52 | 'Table with no keypath or auto increment': function(deferred) {
53 | var req = window.indexedDB.open('IndexedDBPerf');
54 | req.onsuccess = function() {
55 | var transaction = req.result.transaction(['Table1'], "readwrite");
56 | var objStore = transaction.objectStore("Table1");
57 | var addReq = objStore.add(data, window.key++);
58 | addReq.onsuccess = function() {
59 | deferred.resolve();
60 | }
61 | addReq.onerror = function() {
62 | console.log("Could not add data", addReq.error);
63 | };
64 | };
65 | req.onerror = function() {
66 | console.log("Could not Open DB");
67 | };
68 | },
69 | 'Table with keypath and auto increment': function(deferred) {
70 | var req = window.indexedDB.open('IndexedDBPerf');
71 | req.onsuccess = function() {
72 | var transaction = req.result.transaction(['Table2'], "readwrite");
73 | var objStore = transaction.objectStore("Table2");
74 | var addReq = objStore.add(data);
75 | addReq.onsuccess = function() {
76 | deferred.resolve();
77 | }
78 | addReq.onerror = function() {
79 | console.log("Could not add data");
80 | };
81 | };
82 | req.onerror = function() {
83 | console.log("Could open DB");
84 | };
85 | },
86 | 'Table with keypath and NO auto increment': function(deferred) {
87 | var req = window.indexedDB.open('IndexedDBPerf');
88 | req.onsuccess = function() {
89 | var transaction = req.result.transaction(['Table3'], "readwrite");
90 | var objStore = transaction.objectStore("Table3");
91 | data.id = window.key++;
92 | var addReq = objStore.add(data);
93 | addReq.onsuccess = function() {
94 | deferred.resolve();
95 | }
96 | addReq.onerror = function() {
97 | console.log("Could not add data");
98 | };
99 | };
100 | req.onerror = function() {
101 | console.log("Could open DB");
102 | };
103 | },
104 | 'Table with NO keypath but auto increment': function(deferred) {
105 | var req = window.indexedDB.open('IndexedDBPerf');
106 | req.onsuccess = function() {
107 | var transaction = req.result.transaction(['Table4'], "readwrite");
108 | var objStore = transaction.objectStore("Table4");
109 | var addReq = objStore.add(data);
110 | addReq.onsuccess = function() {
111 | deferred.resolve();
112 | }
113 | addReq.onerror = function() {
114 | console.log("Could not add data");
115 | };
116 | };
117 | req.onerror = function() {
118 | console.log("Could open DB");
119 | };
120 | },
121 | 'Table with Index': function(deferred) {
122 | var req = window.indexedDB.open('IndexedDBPerf');
123 | req.onsuccess = function() {
124 | var transaction = req.result.transaction(['Table4'], "readwrite");
125 | var objStore = transaction.objectStore("Table4");
126 | var addReq = objStore.add(data);
127 | addReq.onsuccess = function() {
128 | deferred.resolve();
129 | }
130 | addReq.onerror = function() {
131 | console.log("Could not add data");
132 | };
133 | };
134 | req.onerror = function() {
135 | console.log("Could open DB");
136 | };
137 | }
138 | }
139 | };
140 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/3_TransactionRead.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Transaction based on Read'] = {
3 | category: 'Transaction',
4 | desc: 'Should read requests be queued in a single transaction, or will it be faster to open multiple transactions and read in batches',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBjIjagUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | 'schema': {
10 | '1': function(trans) {
11 | trans.createObjectStore('Table1', {
12 | 'autoIncrement': true
13 | });
14 | }
15 | }
16 | }).done(function() {
17 | var objStore = $.indexedDB('IndexedDBPerf').objectStore('Table1');
18 | var added = 0;
19 | for (var i = 0; i < 1000; i++) {
20 | objStore.add(Faker.Helpers.createCard()).always(function() {
21 | if (++added >= 999) {
22 | cb();
23 | }
24 | status();
25 | });
26 | }
27 | });
28 | });
29 | },
30 | setup: function() {
31 | var data = Faker.Helpers.createCard();
32 | },
33 | teardown: function() {
34 |
35 | },
36 | tests: {
37 | 'All Reads in One Transaction': function(deferred) {
38 | var req = window.indexedDB.open('IndexedDBPerf');
39 | var readCount = 0;
40 | req.onsuccess = function() {
41 | var db = req.result;
42 | var transaction = db.transaction(['Table1'], 'readonly');
43 | var objStore = transaction.objectStore('Table1');
44 | for (var i = 0; i < 1000; i++) {
45 | (function(i) {
46 | var readReq = objStore.get(i);
47 | readReq.onsuccess = readReq.onerror = function() {
48 | if (++readCount >= 999) {
49 | db.close()
50 | deferred.resolve();
51 | }
52 | }
53 | }(i));
54 | }
55 |
56 | };
57 | req.onerror = function() {
58 | throw "Could not open database";
59 | }
60 | },
61 | 'Group reads in transaction sets with 10 reads each': function(deferred) {
62 | var req = window.indexedDB.open('IndexedDBPerf');
63 | var readCount = 0;
64 | req.onsuccess = function() {
65 | var db = req.result;
66 | //console.log("Database opened");
67 | for (var i = 0; i < 10; i++) {
68 | var transaction = db.transaction(['Table1'], 'readonly');
69 | var objStore = transaction.objectStore('Table1');
70 | for (var j = 0; j < 100; j++) {
71 | (function(i) {
72 | var readReq = objStore.get(i);
73 | readReq.onsuccess = readReq.onerror = function() {
74 | if (++readCount >= 999) {
75 | db.close();
76 | deferred.resolve();
77 | }
78 | }
79 | }(i));
80 | }
81 |
82 | }
83 | };
84 | req.onerror = function() {
85 | throw "Could not open database";
86 | }
87 | },
88 | 'Each read in its own transaction': function(deferred) {
89 | var req = window.indexedDB.open('IndexedDBPerf');
90 | var readCount = 0;
91 | req.onsuccess = function() {
92 | var db = req.result;
93 | //console.log("Database opened");
94 | for (var i = 0; i < 1000; i++) {
95 | (function(i) {
96 | var transaction = db.transaction(['Table1'], 'readonly');
97 | var objStore = transaction.objectStore('Table1');
98 | //console.log('Multiple transactions - Reading ', i)
99 | var readReq = objStore.get(i);
100 | readReq.onsuccess = readReq.onerror = function() {
101 | if (++readCount >= 999) {
102 | db.close();
103 | deferred.resolve();
104 | }
105 | }
106 | }(i));
107 | }
108 | };
109 | req.onerror = function() {
110 | throw "Could not open database";
111 | }
112 | }
113 | }
114 | };
115 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/4_TransactionWrite.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Transaction based on Write'] = {
3 | category: 'Transaction',
4 | desc : 'Is it faster to queue all write requests in one transaction, or batch write requests in multiple transactions opening in a loop',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBjDk6QUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | status();
9 | $.indexedDB('IndexedDBPerf', {
10 | 'schema': {
11 | '1': function(trans) {
12 | trans.createObjectStore('Table1', {
13 | 'autoIncrement': true
14 | });
15 | }
16 | }
17 | }).done(function() {
18 | var objStore = $.indexedDB('IndexedDBPerf').objectStore('Table1');
19 | var added = 0;
20 | for (var i = 0; i < 1000; i++) {
21 | objStore.add(Faker.Helpers.createCard()).always(function() {
22 | if (++added >= 999) {
23 | cb();
24 | }
25 | status();
26 | });
27 | }
28 | });
29 | });
30 | },
31 | setup: function() {
32 | var data = Faker.Helpers.createCard();
33 | },
34 | teardown: function() {
35 |
36 | },
37 | tests: {
38 | 'All Writes in One Transaction': function(deferred) {
39 | var req = window.indexedDB.open('IndexedDBPerf');
40 | var readCount = 0;
41 | req.onsuccess = function() {
42 | var db = req.result;
43 | var transaction = db.transaction(['Table1'], 'readwrite');
44 | var objStore = transaction.objectStore('Table1');
45 | //console.log("Database opened");
46 | for (var i = 0; i < 1000; i++) {
47 | //console.log('Single Transaction - reading ', i)
48 | var readReq = objStore.add(data);
49 | readReq.onsuccess = readReq.onerror = function() {
50 | if (++readCount >= 999) {
51 | db.close()
52 | deferred.resolve();
53 | }
54 | }
55 | }
56 |
57 | };
58 | req.onerror = function() {
59 | throw "Could not open database";
60 | }
61 | },
62 | 'Group write in transaction sets with 10 reads each': function(deferred) {
63 | var req = window.indexedDB.open('IndexedDBPerf');
64 | var readCount = 0;
65 | req.onsuccess = function() {
66 | var db = req.result;
67 | //console.log("Database opened");
68 | for (var i = 0; i < 10; i++) {
69 | var transaction = db.transaction(['Table1'], 'readwrite');
70 | var objStore = transaction.objectStore('Table1');
71 | for (var j = 0; j < 100; j++) {
72 | //console.log('Transactions Sets - Reading ', i)
73 | var readReq = objStore.add(data);
74 | readReq.onsuccess = readReq.onerror = function() {
75 | if (++readCount >= 999) {
76 | db.close();
77 | deferred.resolve();
78 | }
79 | }
80 | }
81 |
82 | }
83 | };
84 | req.onerror = function() {
85 | throw "Could not open database";
86 | }
87 | },
88 | 'Each write in its own transaction': function(deferred) {
89 | var req = window.indexedDB.open('IndexedDBPerf');
90 | var readCount = 0;
91 | req.onsuccess = function() {
92 | var db = req.result;
93 | //console.log("Database opened");
94 | for (var i = 0; i < 1000; i++) {
95 | var transaction = db.transaction(['Table1'], 'readwrite');
96 | var objStore = transaction.objectStore('Table1');
97 | //console.log('Multiple transactions - Reading ', i)
98 | var readReq = objStore.add(data);
99 | readReq.onsuccess = readReq.onerror = function() {
100 | if (++readCount >= 999) {
101 | db.close();
102 | deferred.resolve();
103 | }
104 | }
105 | }
106 | };
107 | req.onerror = function() {
108 | throw "Could not open database";
109 | }
110 | }
111 | }
112 | };
113 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/5_Cursor_ParallelWrite.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Cursors - Parallel Write'] = {
3 | category: 'Cursors',
4 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBi9uqkUDA',
5 | desc: 'Is it faster to write all data in one cursor, or segment the data and open multiple cursors in parallel to write them',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | status();
9 | $.indexedDB('IndexedDBPerf', {
10 | 'schema': {
11 | '1': function(trans) {
12 | trans.createObjectStore('Table1', {
13 | 'autoIncrement': true
14 | });
15 | }
16 | }
17 | }).done(function() {
18 | var objStore = $.indexedDB('IndexedDBPerf').objectStore('Table1');
19 | var added = 0;
20 | for (var i = 0; i < 1000; i++) {
21 | objStore.add(Faker.Helpers.createCard()).always(function() {
22 | if (++added >= 999) {
23 | cb();
24 | }
25 | status()
26 | });
27 | }
28 | });
29 | });
30 | },
31 | setup: function() {
32 | var data = Faker.Helpers.createCard();
33 | },
34 | teardown: function() {
35 |
36 | },
37 | tests: {
38 | 'All Write in One cursor': function(deferred) {
39 | var req = window.indexedDB.open('IndexedDBPerf');
40 | var readCount = 0;
41 | req.onsuccess = function() {
42 | var db = req.result;
43 | var transaction = db.transaction(['Table1'], 'readwrite');
44 | var objStore = transaction.objectStore('Table1');
45 | var cursorReq = objStore.openCursor(IDBKeyRange.bound(0, 1000, true, true), "next");
46 | cursorReq.onsuccess = function() {
47 | if (cursorReq.result) {
48 | var data = cursorReq.result.value;
49 | data.modified = true;
50 | cursorReq.result.update(data);
51 | cursorReq.result["continue"]();
52 | } else {
53 | //console.log("All Done");
54 | db.close();
55 | deferred.resolve();
56 | }
57 | };
58 | cursorReq.onerror = function() {
59 | throw "Could not create Cursor request"
60 | }
61 | };
62 | req.onerror = function() {
63 | throw "Could not open database";
64 | };
65 | },
66 | '10 cursors, 100 writes per cursor': function(deferred) {
67 | var req = window.indexedDB.open('IndexedDBPerf');
68 | var readCount = 0;
69 | req.onsuccess = function() {
70 | var db = req.result;
71 | var transaction = db.transaction(['Table1'], 'readwrite');
72 | var objStore = transaction.objectStore('Table1');
73 | var cursorReqs = [],
74 | cursorDoneCount = 0;
75 | for (var i = 0; i < 10; i++) {
76 | (function(i) {
77 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i * 100 + 1, i * 100 + 100, true, true), "next");
78 | cursorReqs[i].onsuccess = function(e) {
79 | if (cursorReqs[i].result) {
80 | var data = cursorReqs[i].result.value;
81 | data.modified = true;
82 | cursorReqs[i].result.update(data);
83 | cursorReqs[i].result["continue"]();
84 | } else {
85 | if (++cursorDoneCount >= 10) {
86 | db.close();
87 | deferred.resolve();
88 | }
89 | }
90 | }
91 | cursorReqs[i].onerror = function(e) {
92 | throw "Could not open Cursor";
93 | }
94 | }(i));
95 | }
96 | };
97 | req.onerror = function() {
98 | throw "Could not open database";
99 | };
100 | },
101 | '100 cursors, 10 writes per cursor': function() {
102 | var req = window.indexedDB.open('IndexedDBPerf');
103 | var readCount = 0;
104 | req.onsuccess = function() {
105 | var db = req.result;
106 | var transaction = db.transaction(['Table1'], 'readwrite');
107 | var objStore = transaction.objectStore('Table1');
108 | var cursorReqs = [],
109 | cursorDoneCount = 0;
110 | for (var i = 0; i < 100; i++) {
111 | (function(i) {
112 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i * 10 + 1, i * 10 + 10, true, true), "next");
113 | cursorReqs[i].onsuccess = function(e) {
114 | if (cursorReqs[i].result) {
115 | var data = cursorReqs[i].result.value;
116 | data.modified = true;
117 | cursorReqs[i].result.update(data);
118 | cursorReqs[i].result["continue"]();
119 | } else {
120 | if (++cursorDoneCount >= 100) {
121 | db.close();
122 | deferred.resolve();
123 | }
124 | }
125 | }
126 | cursorReqs[i].onerror = function(e) {
127 | throw "Could not open Cursor";
128 | }
129 | }(i));
130 | }
131 | };
132 | req.onerror = function() {
133 | throw "Could not open database";
134 | };
135 | },
136 | '500 cursors, 2 writes per cursor': function() {
137 | var req = window.indexedDB.open('IndexedDBPerf');
138 | var readCount = 0;
139 | req.onsuccess = function() {
140 | var db = req.result;
141 | var transaction = db.transaction(['Table1'], 'readwrite');
142 | var objStore = transaction.objectStore('Table1');
143 | var cursorReqs = [],
144 | cursorDoneCount = 0;
145 | for (var i = 0; i < 500; i++) {
146 | (function(i) {
147 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i * 2, i * 2 + 1, true, true), "next");
148 | cursorReqs[i].onsuccess = function(e) {
149 | if (cursorReqs[i].result) {
150 | var data = cursorReqs[i].result.value;
151 | data.modified = true;
152 | cursorReqs[i].result.update(data);
153 | cursorReqs[i].result["continue"]();
154 | } else {
155 | if (++cursorDoneCount >= 500) {
156 | db.close();
157 | deferred.resolve();
158 | }
159 | }
160 | }
161 | cursorReqs[i].onerror = function(e) {
162 | throw "Could not open Cursor";
163 | }
164 | }(i));
165 | }
166 | };
167 | req.onerror = function() {
168 | throw "Could not open database";
169 | };
170 | },
171 | '1000 cursors, 1 writes per cursor': function() {
172 | var req = window.indexedDB.open('IndexedDBPerf');
173 | var readCount = 0;
174 | req.onsuccess = function() {
175 | var db = req.result;
176 | var transaction = db.transaction(['Table1'], 'readwrite');
177 | var objStore = transaction.objectStore('Table1');
178 | var cursorReqs = [],
179 | cursorDoneCount = 0;
180 | for (var i = 0; i < 1000; i++) {
181 | (function(i) {
182 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i, i), "next");
183 | cursorReqs[i].onsuccess = function(e) {
184 | if (cursorReqs[i].result) {
185 | var data = cursorReqs[i].result.value;
186 | data.modified = true;
187 | cursorReqs[i].result.update(data);
188 | cursorReqs[i].result["continue"]();
189 | } else {
190 | if (++cursorDoneCount >= 1000) {
191 | db.close();
192 | deferred.resolve();
193 | }
194 | }
195 | }
196 | cursorReqs[i].onerror = function(e) {
197 | throw "Could not open Cursor";
198 | }
199 | }(i));
200 | }
201 | };
202 | req.onerror = function() {
203 | throw "Could not open database";
204 | };
205 | }
206 | }
207 | };
208 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/6_Cursor_ParallelRead.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Cursors - Parallel Read'] = {
3 | category : 'Cursors',
4 | desc :'Is it faster to read all data in one cursor, or segment the data and open multiple cursors in parallel to read them',
5 | _bTestKey : 'agt1YS1wcm9maWxlcnINCxIEVGVzdBjXtKgUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | 'schema': {
10 | '1': function(trans) {
11 | trans.createObjectStore('Table1', {
12 | 'autoIncrement': true
13 | });
14 | }
15 | }
16 | }).done(function() {
17 | var objStore = $.indexedDB('IndexedDBPerf').objectStore('Table1');
18 | var added = 0;
19 | for (var i = 0; i < 1000; i++) {
20 | objStore.add(Faker.Helpers.createCard()).always(function() {
21 | if (++added >= 999) {
22 | cb();
23 | }
24 | status();
25 | });
26 | }
27 | });
28 | });
29 | },
30 | setup: function() {
31 | var data = Faker.Helpers.createCard();
32 | },
33 | teardown: function() {
34 |
35 | },
36 | tests: {
37 | 'All Read in One cursor': function(deferred) {
38 | var req = window.indexedDB.open('IndexedDBPerf');
39 | var readCount = 0;
40 | req.onsuccess = function() {
41 | var db = req.result;
42 | var transaction = db.transaction(['Table1'], 'readonly');
43 | var objStore = transaction.objectStore('Table1');
44 | var cursorReq = objStore.openCursor(IDBKeyRange.bound(0, 1000, true, true), "next");
45 | cursorReq.onsuccess = function() {
46 | if (cursorReq.result) {
47 | //console.log(cursorReq.result);
48 | cursorReq.result["continue"]();
49 | } else {
50 | //console.log("All Done");
51 | db.close();
52 | deferred.resolve();
53 | }
54 | };
55 | cursorReq.onerror = function() {
56 | throw "Could not create Cursor request"
57 | }
58 | };
59 | req.onerror = function() {
60 | throw "Could not open database";
61 | };
62 | },
63 | '10 cursors, 100 reads per cursor': function(deferred) {
64 | var req = window.indexedDB.open('IndexedDBPerf');
65 | var readCount = 0;
66 | req.onsuccess = function() {
67 | var db = req.result;
68 | var transaction = db.transaction(['Table1'], 'readonly');
69 | var objStore = transaction.objectStore('Table1');
70 | var cursorReqs = [],
71 | cursorDoneCount = 0;
72 | for (var i = 0; i < 10; i++) {
73 | (function(i) {
74 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i * 100 + 1, i * 100 + 100, true, true), "next");
75 | cursorReqs[i].onsuccess = function(e) {
76 | if (cursorReqs[i].result) {
77 | //console.log(cursorReqs[i].result);
78 | cursorReqs[i].result["continue"]();
79 | } else {
80 | if (++cursorDoneCount >= 10) {
81 | db.close();
82 | deferred.resolve();
83 | }
84 | }
85 | }
86 | cursorReqs[i].onerror = function(e) {
87 | throw "Could not open Cursor";
88 | }
89 | }(i));
90 | }
91 | };
92 | req.onerror = function() {
93 | throw "Could not open database";
94 | };
95 | },
96 | '100 cursors, 10 reads per cursor': function() {
97 | var req = window.indexedDB.open('IndexedDBPerf');
98 | var readCount = 0;
99 | req.onsuccess = function() {
100 | var db = req.result;
101 | var transaction = db.transaction(['Table1'], 'readonly');
102 | var objStore = transaction.objectStore('Table1');
103 | var cursorReqs = [],
104 | cursorDoneCount = 0;
105 | for (var i = 0; i < 100; i++) {
106 | (function(i) {
107 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i * 10 + 1, i * 10 + 10, true, true), "next");
108 | cursorReqs[i].onsuccess = function(e) {
109 | if (cursorReqs[i].result) {
110 | //console.log(cursorReqs[i].result);
111 | cursorReqs[i].result["continue"]();
112 | } else {
113 | if (++cursorDoneCount >= 100) {
114 | db.close();
115 | deferred.resolve();
116 | }
117 | }
118 | }
119 | cursorReqs[i].onerror = function(e) {
120 | throw "Could not open Cursor";
121 | }
122 | }(i));
123 | }
124 | };
125 | req.onerror = function() {
126 | throw "Could not open database";
127 | };
128 | },
129 | '500 cursors, 2 reads per cursor': function() {
130 | var req = window.indexedDB.open('IndexedDBPerf');
131 | var readCount = 0;
132 | req.onsuccess = function() {
133 | var db = req.result;
134 | var transaction = db.transaction(['Table1'], 'readonly');
135 | var objStore = transaction.objectStore('Table1');
136 | var cursorReqs = [],
137 | cursorDoneCount = 0;
138 | for (var i = 0; i < 500; i++) {
139 | (function(i) {
140 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i * 2, i * 2 + 1, true, true), "next");
141 | cursorReqs[i].onsuccess = function(e) {
142 | if (cursorReqs[i].result) {
143 | //console.log(cursorReqs[i].result);
144 | cursorReqs[i].result["continue"]();
145 | } else {
146 | if (++cursorDoneCount >= 500) {
147 | db.close();
148 | deferred.resolve();
149 | }
150 | }
151 | }
152 | cursorReqs[i].onerror = function(e) {
153 | throw "Could not open Cursor";
154 | }
155 | }(i));
156 | }
157 | };
158 | req.onerror = function() {
159 | throw "Could not open database";
160 | };
161 | },
162 | '1000 cursors, 1 read per cursor': function() {
163 | var req = window.indexedDB.open('IndexedDBPerf');
164 | var readCount = 0;
165 | req.onsuccess = function() {
166 | var db = req.result;
167 | var transaction = db.transaction(['Table1'], 'readonly');
168 | var objStore = transaction.objectStore('Table1');
169 | var cursorReqs = [],
170 | cursorDoneCount = 0;
171 | for (var i = 0; i < 1000; i++) {
172 | (function(i) {
173 | cursorReqs[i] = objStore.openCursor(IDBKeyRange.bound(i, i), "next");
174 | cursorReqs[i].onsuccess = function(e) {
175 | if (cursorReqs[i].result) {
176 | //console.log(cursorReqs[i].result);
177 | cursorReqs[i].result["continue"]();
178 | } else {
179 | if (++cursorDoneCount >= 1000) {
180 | db.close();
181 | deferred.resolve();
182 | }
183 | }
184 | }
185 | cursorReqs[i].onerror = function(e) {
186 | throw "Could not open Cursor";
187 | }
188 | }(i));
189 | }
190 | };
191 | req.onerror = function() {
192 | throw "Could not open database";
193 | };
194 | }
195 | }
196 | };
197 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/8_IndexUnused.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Indexes - Used vs Unused Indexes'] = {
3 | category : 'Indexes',
4 | desc : 'Does adding unused Indexes slow down the speed at which data is written to an object store',
5 | _bTestKey: 'agt1YS1wcm9maWxlcnINCxIEVGVzdBj14KkUDA',
6 | onStart: function(cb) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | schema: {
10 | 1: function(transaction) {
11 | var table1 = transaction.createObjectStore("Table1", {
12 | 'autoIncrement': true
13 | });
14 |
15 | var table2 = transaction.createObjectStore("Table2", {
16 | 'autoIncrement': true
17 | });
18 | table2.createIndex("name");
19 |
20 | var table3 = transaction.createObjectStore("Table3", {
21 | 'autoIncrement': true
22 | });
23 | table3.createIndex("unusedindex");
24 | }
25 | }
26 | }).done(function() {
27 | cb();
28 | });
29 | });
30 |
31 | window.addData = function(table, deferred) {
32 | var req = window.indexedDB.open('IndexedDBPerf');
33 | var readCount = 0;
34 | req.onsuccess = function() {
35 | var db = req.result;
36 | var transaction = db.transaction([table], 'readwrite');
37 | var objStore = transaction.objectStore(table);
38 | var writeReq = objStore.add(data);
39 | writeReq.onsuccess = function() {
40 | db.close();
41 | deferred.resolve();
42 | };
43 | };
44 | req.onerror = function() {
45 | throw "Could not open database";
46 | };
47 | }
48 | },
49 | setup: function() {
50 | window.data = Faker.Helpers.createCard();
51 | },
52 | teardown: function() {
53 |
54 | },
55 | tests: {
56 | 'Writing to a table with NO index': function(deferred) {
57 | addData("Table1", deferred);
58 | },
59 | 'Writing to a table with Used index': function(deferred) {
60 | addData("Table2", deferred);
61 | },
62 | 'Writing to a table with Unused index': function(deferred) {
63 | addData("Table3", deferred);
64 | }
65 | }
66 | };
67 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/9_CursorIndexCursor.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Iterations using Cursors/Index Cursors'] = {
3 | category : 'Indexes',
4 | desc: 'Is iterating using Indexes as fast as Iterating using normal cursors',
5 | _bTestKey:'agt1YS1wcm9maWxlcnINCxIEVGVzdBj35qcUDA',
6 | onStart: function(cb, status) {
7 | $.indexedDB('IndexedDBPerf').deleteDatabase().done(function() {
8 | $.indexedDB('IndexedDBPerf', {
9 | 'schema': {
10 | 1: function(t) {
11 | var table1 = t.createObjectStore("Table1", {
12 | autoIncrement: false,
13 | keyPath : "id"
14 | });
15 | table1.createIndex("id");
16 | table1.createIndex("name");
17 | }
18 | }
19 | }).done(function() {
20 | var objStore = $.indexedDB('IndexedDBPerf').objectStore('Table1');
21 | var added = 0;
22 | for (var i = 0; i < 1000; i++) {
23 | var data = Faker.Helpers.createCard();
24 | data.name = i + Faker.Name.findName();
25 | data.id = i;
26 | objStore.add(data).always(function() {
27 | if (++added >= 999) {
28 | cb();
29 | }
30 | status();
31 | });
32 | }
33 | })
34 | });
35 | },
36 | setup: function() {},
37 | teardown: function() {},
38 | tests: {
39 | 'Reading using Cursors': function(deferred) {
40 | var req = window.indexedDB.open('IndexedDBPerf');
41 | var readCount = 0;
42 | req.onsuccess = function() {
43 | var db = req.result;
44 | var transaction = db.transaction(['Table1'], 'readonly');
45 | var objStore = transaction.objectStore('Table1');
46 | var cursorReq = objStore.openCursor(IDBKeyRange.bound(0, 1000, true, true), "next");
47 | cursorReq.onsuccess = function() {
48 | if (cursorReq.result) {
49 | var data = cursorReq.result.value;
50 | readCount++;
51 | cursorReq.result["continue"]();
52 | } else {
53 | //console.log("All Done");
54 | if (readCount < 999){
55 | throw "Did not read all the data" + readCount;
56 | }
57 | db.close();
58 | deferred.resolve();
59 | }
60 | };
61 | cursorReq.onerror = function() {
62 | throw "Could not create Cursor request"
63 | }
64 | };
65 | req.onerror = function() {
66 | throw "Could not open database";
67 | };
68 | },
69 | 'Reading using Index Cursors': function(deferred) {
70 | var req = window.indexedDB.open('IndexedDBPerf');
71 | var readCount = 0;
72 | req.onsuccess = function() {
73 | var db = req.result;
74 | var transaction = db.transaction(['Table1'], 'readonly');
75 | var objStore = transaction.objectStore('Table1');
76 | var index = objStore.index("id");
77 | var cursorReq = index.openCursor(IDBKeyRange.bound(0, 1000, true, true), "next");
78 | cursorReq.onsuccess = function() {
79 | if (cursorReq.result) {
80 | var data = cursorReq.result.value;
81 | readCount++;
82 | cursorReq.result["continue"]();
83 | } else {
84 | if (readCount < 999){
85 | throw "Did not read all the data" + readCount;
86 | }
87 | db.close();
88 | deferred.resolve();
89 | }
90 | };
91 | cursorReq.onerror = function() {
92 | throw "Could not create Cursor request"
93 | }
94 | };
95 | req.onerror = function() {
96 | throw "Could not open database";
97 | };
98 | },
99 | 'Reading using Index Cursors - String Index': function(deferred) {
100 | var req = window.indexedDB.open('IndexedDBPerf');
101 | var readCount = 0;
102 | req.onsuccess = function() {
103 | var db = req.result;
104 | var transaction = db.transaction(['Table1'], 'readonly');
105 | var objStore = transaction.objectStore('Table1');
106 | var index = objStore.index("name");
107 | var cursorReq = index.openCursor();
108 | cursorReq.onsuccess = function() {
109 | if (cursorReq.result) {
110 | var data = cursorReq.result.value;
111 | readCount++;
112 | cursorReq.result["continue"]();
113 | } else {
114 | if (readCount < 999){
115 | throw "Did not read all the data " + readCount;
116 | }
117 | db.close();
118 | deferred.resolve();
119 | }
120 | };
121 | cursorReq.onerror = function() {
122 | throw "Could not create Cursor request"
123 | }
124 | };
125 | req.onerror = function() {
126 | throw "Could not open database";
127 | };
128 | }
129 | }
130 | };
131 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/perf/tests/Template.js:
--------------------------------------------------------------------------------
1 | (function(s) {
2 | s['Template'] = {
3 | category: '',
4 | desc: '',
5 | _bTestKey: '',
6 | onStart: function(cb, status) {
7 | cb();
8 | },
9 | setup: function() {},
10 | teardown: function() {},
11 | defer: true,
12 | tests: {
13 | 'Test 1': function(deferred) {
14 | window.setTimeout(function() {
15 | deferred.resolve();
16 | }, 1000);
17 | },
18 | 'Test 2': function(deferred) {
19 | window.setTimeout(function() {
20 | deferred.resolve();
21 | }, 2000);
22 | }
23 | }
24 | };
25 | }(window.IndexedDBPerf.suites));
--------------------------------------------------------------------------------
/polyfill/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: Helvetica Neue, Verdana, Helvetica, Arial;
5 | font-size: 14px;
6 | color: #333;
7 | }
8 |
9 | body {
10 | overflow: auto;
11 | height: 100%;
12 | background: #6788AD;
13 | line-height : 18px;
14 | background: -moz-linear-gradient(top, #496687 0%, #6889AE 100%);
15 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #496687), color-stop(100%, #6889AE) );
16 | filter: progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#496687', endColorstr = '#6889AE',GradientType = 0 );
17 | }
18 |
19 | li{
20 | margin-bottom:3px;
21 | }
22 |
23 | #content-wrap{
24 | width : 70%;
25 | margin : 0 auto;
26 | background-color : white;
27 | box-shadow : 0 0 20px #122F4B;
28 | }
29 |
30 | h1{
31 | padding : 1%;
32 | background-color : #122F4B;
33 | color: white;
34 | font-family: Georgia, "Times New Roman", Times;
35 | font-weight : normal;
36 | text-align : center;
37 | padding : 20px 0;
38 | margin : 0;
39 | }
40 |
41 | h2{
42 | border-top : dotted 1px #777;
43 | padding-top : 10px;
44 | margin-top: 10px;
45 | }
46 |
47 | #content{
48 | padding : 2%;
49 | }
50 |
--------------------------------------------------------------------------------
/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | IndexedDB - Test file
5 |
6 |
7 |
8 | Links for each function that is tested would be generated here.
9 |
10 |
211 |
212 |
213 |
--------------------------------------------------------------------------------
/trialtool/all.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 | -
7 |
8 | -
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/trialtool/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Test Page
4 |
5 |
6 |
7 |
8 |
10 |
12 |
42 |
43 |
44 |
--------------------------------------------------------------------------------