Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: chrome/test/data/indexeddb/perf_shared.js

Issue 10826038: Add more IDB perf tests, including cursor reads and log-style writes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Made most of Josh's tweaks. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/test/data/indexeddb/perf_test.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 window.indexedDB = window.indexedDB || window.webkitIndexedDB || 5 window.indexedDB = window.indexedDB || window.webkitIndexedDB ||
6 window.mozIndexedDB || window.msIndexedDB; 6 window.mozIndexedDB || window.msIndexedDB;
7 window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
7 8
8 var automation = { 9 var automation = {
9 results: {} 10 results: {}
10 }; 11 };
11 12
12 automation.setDone = function() { 13 automation.setDone = function() {
13 this.setStatus("Test complete."); 14 this.setStatus("Test complete.");
14 document.cookie = '__done=1; path=/'; 15 document.cookie = '__done=1; path=/';
15 }; 16 };
16 17
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 var baseVersion = 2; // The version with our object stores. 53 var baseVersion = 2; // The version with our object stores.
53 var curVersion; 54 var curVersion;
54 55
55 // Valid options fields: 56 // Valid options fields:
56 // indexName: the name of an index to create on each object store 57 // indexName: the name of an index to create on each object store
57 // indexKeyPath: the key path for that index 58 // indexKeyPath: the key path for that index
58 // indexIsUnique: the "unique" option for IDBIndexParameters 59 // indexIsUnique: the "unique" option for IDBIndexParameters
59 // indexIsMultiEntry: the "multiEntry" option for IDBIndexParameters 60 // indexIsMultiEntry: the "multiEntry" option for IDBIndexParameters
60 // 61 //
61 function createDatabase( 62 function createDatabase(
62 name, objectStoreNames, handler, errorHandler, options) { 63 name, objectStoreNames, handler, errorHandler, optionSets) {
63 var openRequest = indexedDB.open(name, baseVersion); 64 var openRequest = indexedDB.open(name, baseVersion);
64 openRequest.onblocked = errorHandler; 65 openRequest.onblocked = errorHandler;
65 function createObjectStores(db) { 66 function createObjectStores(db) {
66 for (var store in objectStoreNames) { 67 for (var store in objectStoreNames) {
67 var name = objectStoreNames[store]; 68 var name = objectStoreNames[store];
68 assert(!db.objectStoreNames.contains(name)); 69 assert(!db.objectStoreNames.contains(name));
69 var os = db.createObjectStore(name); 70 var os = db.createObjectStore(name);
70 if (options && options.indexName) { 71 if (optionSets) {
71 assert('indexKeyPath' in options); 72 for (o in optionSets) {
72 os.createIndex(options.indexName, options.indexKeyPath, 73 var options = optionSets[o];
73 { unique: options.indexIsUnique, 74 assert(options.indexName);
74 multiEntry: options.indexIsMultiEntry }); 75 assert('indexKeyPath' in options);
76 os.createIndex(options.indexName, options.indexKeyPath,
77 { unique: options.indexIsUnique,
78 multiEntry: options.indexIsMultiEntry });
79 }
75 } 80 }
76 } 81 }
77 } 82 }
78 openRequest.onupgradeneeded = function(ev) { 83 openRequest.onupgradeneeded = function(ev) {
79 // TODO: This is the spec-compliant path, which doesn't yet work in Chrome, 84 // TODO(ericu): This is the spec-compliant path, which doesn't yet work in
80 // and isn't yet tested, as this function won't currently be called. 85 // Chrome, and isn't yet tested, as this function won't currently be called.
81 assert(openRequest == ev.target); 86 assert(openRequest == ev.target);
82 createObjectStores(openRequest.result); 87 createObjectStores(openRequest.result);
83 // onsuccess will get called after this exits. 88 // onsuccess will get called after this exits.
84 }; 89 };
85 openRequest.onsuccess = function(ev) { 90 openRequest.onsuccess = function(ev) {
86 assert(openRequest == ev.target); 91 assert(openRequest == ev.target);
87 var db = openRequest.result; 92 var db = openRequest.result;
88 db.onerror = function(ev) { 93 db.onerror = function(ev) {
89 console.log("db error", arguments, openRequest.webkitErrorMessage); 94 console.log("db error", arguments, openRequest.webkitErrorMessage);
90 errorHandler(); 95 errorHandler();
(...skipping 15 matching lines...) Expand all
106 } 111 }
107 } 112 }
108 } 113 }
109 114
110 // You must close all database connections before calling this. 115 // You must close all database connections before calling this.
111 function alterObjectStores( 116 function alterObjectStores(
112 name, objectStoreNames, func, handler, errorHandler) { 117 name, objectStoreNames, func, handler, errorHandler) {
113 var version = curVersion + 1; 118 var version = curVersion + 1;
114 var openRequest = indexedDB.open(name, version); 119 var openRequest = indexedDB.open(name, version);
115 openRequest.onblocked = errorHandler; 120 openRequest.onblocked = errorHandler;
116 // TODO: This won't work in Firefox yet; see above in createDatabase. 121 // TODO(ericu): This won't work in Firefox yet; see above in createDatabase.
117 openRequest.onsuccess = function(ev) { 122 openRequest.onsuccess = function(ev) {
118 assert(openRequest == ev.target); 123 assert(openRequest == ev.target);
119 var db = openRequest.result; 124 var db = openRequest.result;
120 db.onerror = function(ev) { 125 db.onerror = function(ev) {
121 console.log("error altering db", arguments, 126 console.log("error altering db", arguments,
122 openRequest.webkitErrorMessage); 127 openRequest.webkitErrorMessage);
123 errorHandler(); 128 errorHandler();
124 } 129 }
125 if (db.version != version) { 130 if (db.version != version) {
126 var setVersionRequest = db.setVersion(version); 131 var setVersionRequest = db.setVersion(version);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 function getCompletionFunc(testName, startTime, onTestComplete) { 168 function getCompletionFunc(testName, startTime, onTestComplete) {
164 function onDeleted() { 169 function onDeleted() {
165 automation.setStatus("Deleted database."); 170 automation.setStatus("Deleted database.");
166 onTestComplete(); 171 onTestComplete();
167 } 172 }
168 return function() { 173 return function() {
169 var duration = Date.now() - startTime; 174 var duration = Date.now() - startTime;
170 // Ignore the cleanup time for this test. 175 // Ignore the cleanup time for this test.
171 automation.addResult(testName, duration); 176 automation.addResult(testName, duration);
172 automation.setStatus("Deleting database."); 177 automation.setStatus("Deleting database.");
173 // TODO: Turn on actual deletion; for now it's way too slow. 178 // TODO(ericu): Turn on actual deletion; for now it's way too slow.
174 // deleteDatabase(testName, onDeleted); 179 // deleteDatabase(testName, onDeleted);
175 onTestComplete(); 180 onTestComplete();
176 } 181 }
177 } 182 }
178 183
179 function getDisplayName(args) { 184 function getDisplayName(args) {
180 // The last arg is the completion callback the test runner tacks on. 185 // The last arg is the completion callback the test runner tacks on.
186 // TODO(ericu): Make test errors delete the database automatically.
181 return getDisplayName.caller.name + "_" + 187 return getDisplayName.caller.name + "_" +
182 Array.prototype.slice.call(args, 0, args.length - 1).join("_"); 188 Array.prototype.slice.call(args, 0, args.length - 1).join("_");
183 } 189 }
184 190
191 // Pad a string [or object convertible to a string] to a fixed width; use this
192 // to have numeric strings sort properly.
193 function padToWidth(s, width) {
194 s = String(s);
195 assert(s.length <= width);
196 while (s.length < width) {
197 s = "0" + s;
198 }
199 return s;
200 }
201
185 function getSimpleKey(i) { 202 function getSimpleKey(i) {
186 return "key " + i; 203 return "key " + padToWidth(i, 10);
187 } 204 }
188 205
189 function getSimpleValue(i) { 206 function getSimpleValue(i) {
190 return "value " + i; 207 return "value " + padToWidth(i, 10);
208 }
209
210 function getForwardIndexKey(i) {
211 return i;
212 }
213
214 function getBackwardIndexKey(i) {
215 return -i;
216 }
217
218 // This is useful for indexing by keypath; the two names should be ordered in
219 // opposite directions for all i in uint32 range.
220 function getObjectValue(i) {
221 return {
222 firstName: getForwardIndexKey(i),
223 lastName: getBackwardIndexKey(i)
224 };
225 }
226
227 function getNFieldName(k) {
228 return "field" + k;
229 }
230
231 function getNFieldObjectValue(i, n) {
232 assert(Math.floor(n) == n);
233 assert(n > 0);
234 var o = {};
235 for (; n > 0; --n) {
236 // The value varies per field, each object will tend to be unique,
237 // and thanks to the modulus, indexing on different fields will give you
238 // different ordering for large-enough data sets.
239 o[getNFieldName(n - 1)] = Math.pow(i + 0.5, n + 0.5) % 65536;
240 }
241 return o;
191 } 242 }
192 243
193 function putLinearValues( 244 function putLinearValues(
194 transaction, objectStoreNames, numKeys, getKey, getValue) { 245 transaction, objectStoreNames, numKeys, getKey, getValue) {
195 if (!getKey) 246 if (!getKey)
196 getKey = getSimpleKey; 247 getKey = getSimpleKey;
197 if (!getValue) 248 if (!getValue)
198 getValue = getSimpleValue; 249 getValue = getSimpleValue;
199 for (var i in objectStoreNames) { 250 for (var i in objectStoreNames) {
200 var os = transaction.objectStore(objectStoreNames[i]); 251 var os = transaction.objectStore(objectStoreNames[i]);
(...skipping 30 matching lines...) Expand all
231 for (var i in objectStoreNames) { 282 for (var i in objectStoreNames) {
232 var os = transaction.objectStore(objectStoreNames[i]); 283 var os = transaction.objectStore(objectStoreNames[i]);
233 for (var j = 0; j < numPuts; ++j) { 284 for (var j = 0; j < numPuts; ++j) {
234 var rand = Math.floor(Math.random() * numKeys); 285 var rand = Math.floor(Math.random() * numKeys);
235 var request = os.put(getValue(rand), getKey(rand)); 286 var request = os.put(getValue(rand), getKey(rand));
236 request.onerror = onError; 287 request.onerror = onError;
237 } 288 }
238 } 289 }
239 } 290 }
240 291
292 // getKey should be deterministic, as we assume that a cursor that starts at
293 // getKey(X) and runs through getKey(X + K) has exactly K values available.
294 // This is annoying to guarantee generally when using an index, so we avoid both
295 // ends of the key space just in case and use simple indices.
296 // TODO(ericu): Figure out if this can be simplified and we can remove uses of
297 // getObjectValue in favor of getNFieldObjectValue.
298 function getValuesFromCursor(
299 transaction, inputObjectStoreName, numReads, numKeys, indexName, getKey,
300 readKeysOnly, outputObjectStoreName) {
301 assert(2 * numReads < numKeys);
302 if (!getKey)
303 getKey = getSimpleKey;
304 var rand = Math.floor(Math.random() * (numKeys - 2 * numReads)) + numReads;
305 var values = [];
306 var queryObject = transaction.objectStore(inputObjectStoreName);
307 assert(queryObject);
308 if (indexName)
309 queryObject = queryObject.index(indexName);
310 var keyRange = IDBKeyRange.bound(
311 getKey(rand), getKey(rand + numReads), false, true);
312 var request;
313 if (readKeysOnly) {
314 request = queryObject.openKeyCursor(keyRange);
315 } else {
316 request = queryObject.openCursor(keyRange);
317 }
318 var oos;
319 if (outputObjectStoreName)
320 oos = transaction.objectStore(outputObjectStoreName);
321 var numReadsLeft = numReads;
322 request.onsuccess = function(event) {
323 var cursor = event.target.result;
324 if (cursor) {
325 assert(numReadsLeft);
326 --numReadsLeft;
327 if (oos) // Put in random order for maximum difficulty.
328 oos.put(cursor.value, Math.random());
329 values.push({key: cursor.key, value: cursor.value});
330 cursor.continue();
331 } else {
332 assert(!numReadsLeft);
333 }
334 }
335 request.onerror = onError;
336 }
337
338
241 function stringOfLength(n) { 339 function stringOfLength(n) {
242 assert(n > 0); 340 assert(n > 0);
243 assert(n == Math.floor(n)); 341 assert(n == Math.floor(n));
244 return new Array(n + 1).join('0'); 342 return new Array(n + 1).join('0');
245 } 343 }
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/indexeddb/perf_test.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698