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

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: tiny 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
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 7
8 var automation = { 8 var automation = {
9 results: {} 9 results: {}
10 }; 10 };
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 var baseVersion = 2; // The version with our object stores. 52 var baseVersion = 2; // The version with our object stores.
53 var curVersion; 53 var curVersion;
54 54
55 // Valid options fields: 55 // Valid options fields:
56 // indexName: the name of an index to create on each object store 56 // indexName: the name of an index to create on each object store
57 // indexKeyPath: the key path for that index 57 // indexKeyPath: the key path for that index
58 // indexIsUnique: the "unique" option for IDBIndexParameters 58 // indexIsUnique: the "unique" option for IDBIndexParameters
59 // indexIsMultiEntry: the "multiEntry" option for IDBIndexParameters 59 // indexIsMultiEntry: the "multiEntry" option for IDBIndexParameters
60 // 60 //
61 function createDatabase( 61 function createDatabase(
62 name, objectStoreNames, handler, errorHandler, options) { 62 name, objectStoreNames, handler, errorHandler, optionSets) {
63 var openRequest = indexedDB.open(name, baseVersion); 63 var openRequest = indexedDB.open(name, baseVersion);
64 openRequest.onblocked = errorHandler; 64 openRequest.onblocked = errorHandler;
65 function createObjectStores(db) { 65 function createObjectStores(db) {
66 for (var store in objectStoreNames) { 66 for (var store in objectStoreNames) {
67 var name = objectStoreNames[store]; 67 var name = objectStoreNames[store];
68 assert(!db.objectStoreNames.contains(name)); 68 assert(!db.objectStoreNames.contains(name));
69 var os = db.createObjectStore(name); 69 var os = db.createObjectStore(name);
70 if (options && options.indexName) { 70 if (optionSets) {
71 assert('indexKeyPath' in options); 71 for (o in optionSets) {
72 os.createIndex(options.indexName, options.indexKeyPath, 72 var options = optionSets[o];
73 { unique: options.indexIsUnique, 73 assert(options.indexName);
74 multiEntry: options.indexIsMultiEntry }); 74 assert('indexKeyPath' in options);
75 os.createIndex(options.indexName, options.indexKeyPath,
76 { unique: options.indexIsUnique,
77 multiEntry: options.indexIsMultiEntry });
78 }
75 } 79 }
76 } 80 }
77 } 81 }
78 openRequest.onupgradeneeded = function(ev) { 82 openRequest.onupgradeneeded = function(ev) {
79 // TODO: This is the spec-compliant path, which doesn't yet work in Chrome, 83 // 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. 84 // Chrome, and isn't yet tested, as this function won't currently be called.
81 assert(openRequest == ev.target); 85 assert(openRequest == ev.target);
82 createObjectStores(openRequest.result); 86 createObjectStores(openRequest.result);
83 // onsuccess will get called after this exits. 87 // onsuccess will get called after this exits.
84 }; 88 };
85 openRequest.onsuccess = function(ev) { 89 openRequest.onsuccess = function(ev) {
86 assert(openRequest == ev.target); 90 assert(openRequest == ev.target);
87 var db = openRequest.result; 91 var db = openRequest.result;
88 db.onerror = function(ev) { 92 db.onerror = function(ev) {
89 console.log("db error", arguments, openRequest.webkitErrorMessage); 93 console.log("db error", arguments, openRequest.webkitErrorMessage);
90 errorHandler(); 94 errorHandler();
(...skipping 15 matching lines...) Expand all
106 } 110 }
107 } 111 }
108 } 112 }
109 113
110 // You must close all database connections before calling this. 114 // You must close all database connections before calling this.
111 function alterObjectStores( 115 function alterObjectStores(
112 name, objectStoreNames, func, handler, errorHandler) { 116 name, objectStoreNames, func, handler, errorHandler) {
113 var version = curVersion + 1; 117 var version = curVersion + 1;
114 var openRequest = indexedDB.open(name, version); 118 var openRequest = indexedDB.open(name, version);
115 openRequest.onblocked = errorHandler; 119 openRequest.onblocked = errorHandler;
116 // TODO: This won't work in Firefox yet; see above in createDatabase. 120 // TODO(ericu): This won't work in Firefox yet; see above in createDatabase.
117 openRequest.onsuccess = function(ev) { 121 openRequest.onsuccess = function(ev) {
118 assert(openRequest == ev.target); 122 assert(openRequest == ev.target);
119 var db = openRequest.result; 123 var db = openRequest.result;
120 db.onerror = function(ev) { 124 db.onerror = function(ev) {
121 console.log("error altering db", arguments, 125 console.log("error altering db", arguments,
122 openRequest.webkitErrorMessage); 126 openRequest.webkitErrorMessage);
123 errorHandler(); 127 errorHandler();
124 } 128 }
125 if (db.version != version) { 129 if (db.version != version) {
126 var setVersionRequest = db.setVersion(version); 130 var setVersionRequest = db.setVersion(version);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 function getCompletionFunc(testName, startTime, onTestComplete) { 167 function getCompletionFunc(testName, startTime, onTestComplete) {
164 function onDeleted() { 168 function onDeleted() {
165 automation.setStatus("Deleted database."); 169 automation.setStatus("Deleted database.");
166 onTestComplete(); 170 onTestComplete();
167 } 171 }
168 return function() { 172 return function() {
169 var duration = Date.now() - startTime; 173 var duration = Date.now() - startTime;
170 // Ignore the cleanup time for this test. 174 // Ignore the cleanup time for this test.
171 automation.addResult(testName, duration); 175 automation.addResult(testName, duration);
172 automation.setStatus("Deleting database."); 176 automation.setStatus("Deleting database.");
173 // TODO: Turn on actual deletion; for now it's way too slow. 177 // TODO(ericu): Turn on actual deletion; for now it's way too slow.
174 // deleteDatabase(testName, onDeleted); 178 // deleteDatabase(testName, onDeleted);
175 onTestComplete(); 179 onTestComplete();
176 } 180 }
177 } 181 }
178 182
179 function getDisplayName(args) { 183 function getDisplayName(args) {
180 // The last arg is the completion callback the test runner tacks on. 184 // The last arg is the completion callback the test runner tacks on.
185 // TODO(ericu): Make test errors delete the database automatically.
181 return getDisplayName.caller.name + "_" + 186 return getDisplayName.caller.name + "_" +
182 Array.prototype.slice.call(args, 0, args.length - 1).join("_"); 187 Array.prototype.slice.call(args, 0, args.length - 1).join("_");
183 } 188 }
184 189
190 // Pad a string [or object convertible to a string] to a fixed width; use this
191 // to have numeric strings sort properly.
192 function padToWidth(s, width) {
193 s = "" + s;
jsbell 2012/07/27 00:25:46 Although it should get optimized to the same thing
ericu 2012/07/31 01:00:53 Done.
194 assert(s.length <= width);
195 while (s.length < width) {
jsbell 2012/07/27 00:25:46 Alternately: (Array(width + 1).join("0") + s).subs
ericu 2012/07/31 01:00:53 I find that shorter, but a bit harder to read, so
196 s = "0" + s;
197 }
198 return s;
199 }
200
185 function getSimpleKey(i) { 201 function getSimpleKey(i) {
186 return "key " + i; 202 return "key " + padToWidth(i, 10);
187 } 203 }
188 204
189 function getSimpleValue(i) { 205 function getSimpleValue(i) {
190 return "value " + i; 206 return "value " + padToWidth(i, 10);
207 }
208
209 function getForwardIndexKey(i) {
210 return i;
211 }
212
213 function getBackwardIndexKey(i) {
214 return -i;
215 }
216
217 // This is useful for indexing by keypath; the two names should be ordered in
218 // opposite directions for all i in uint32 range.
219 function getObjectValue(i) {
220 return {
221 firstName: getForwardIndexKey(i),
222 lastName: getBackwardIndexKey(i)
223 };
224 }
225
226 function getNFieldObjectValue(i, n) {
227 assert(Math.floor(n) == n);
228 assert(n > 0);
229 var o = {};
230 for (; n > 0; --n) {
231 // The value varies per field, each object will tend to be unique,
232 // and thanks to the modulus, indexing on different fields will give you
233 // different ordering for large-enough data sets.
234 o["field" + (n - 1)] = Math.pow(i + 0.5, n + 0.5) % 65536;
235 }
236 return o;
191 } 237 }
192 238
193 function putLinearValues( 239 function putLinearValues(
194 transaction, objectStoreNames, numKeys, getKey, getValue) { 240 transaction, objectStoreNames, numKeys, getKey, getValue) {
195 if (!getKey) 241 if (!getKey)
196 getKey = getSimpleKey; 242 getKey = getSimpleKey;
197 if (!getValue) 243 if (!getValue)
198 getValue = getSimpleValue; 244 getValue = getSimpleValue;
199 for (var i in objectStoreNames) { 245 for (var i in objectStoreNames) {
200 var os = transaction.objectStore(objectStoreNames[i]); 246 var os = transaction.objectStore(objectStoreNames[i]);
(...skipping 30 matching lines...) Expand all
231 for (var i in objectStoreNames) { 277 for (var i in objectStoreNames) {
232 var os = transaction.objectStore(objectStoreNames[i]); 278 var os = transaction.objectStore(objectStoreNames[i]);
233 for (var j = 0; j < numPuts; ++j) { 279 for (var j = 0; j < numPuts; ++j) {
234 var rand = Math.floor(Math.random() * numKeys); 280 var rand = Math.floor(Math.random() * numKeys);
235 var request = os.put(getValue(rand), getKey(rand)); 281 var request = os.put(getValue(rand), getKey(rand));
236 request.onerror = onError; 282 request.onerror = onError;
237 } 283 }
238 } 284 }
239 } 285 }
240 286
287 // getKey should be deterministic, as we assume that a cursor that starts at
288 // getKey(X) and runs through getKey(X + K) has exactly K values available.
289 // This is annoying to guarantee generally when using an index, so we avoid both
290 // ends of the key space just in case and use simple indices.
291 // TODO(ericu): Figure out if this can be simplified and we can remove uses of
292 // getObjectValue in favor of getNFieldObjectValue.
293 function getValuesFromCursor(
294 transaction, inputObjectStoreName, numReads, numKeys, indexName, getKey,
295 readKeysOnly, outputObjectStoreName) {
296 assert(2 * numReads < numKeys);
297 if (!getKey)
298 getKey = getSimpleKey;
299 var rand = Math.floor(Math.random() * (numKeys - 2 * numReads)) + numReads;
300 var values = [];
301 var queryObject = transaction.objectStore(inputObjectStoreName);
302 assert(queryObject);
303 if (indexName)
304 queryObject = queryObject.index(indexName);
305 var keyRange = webkitIDBKeyRange.bound(
jsbell 2012/07/27 00:25:46 Should add at the top of the file: window.IDBKeyRa
ericu 2012/07/31 01:00:53 Done.
306 getKey(rand), getKey(rand + numReads), false, true);
307 var request;
308 if (readKeysOnly) {
309 request = queryObject.openKeyCursor(keyRange);
310 } else {
311 request = queryObject.openCursor(keyRange);
312 }
313 var oos;
314 if (outputObjectStoreName)
315 oos = transaction.objectStore(outputObjectStoreName);
316 var numReadsLeft = numReads;
317 request.onsuccess = function(event) {
318 var cursor = event.target.result;
319 if (cursor) {
320 assert(numReadsLeft);
321 --numReadsLeft;
322 if (oos) // Put in random order for maximum difficulty.
323 oos.put(cursor.value, Math.random());
324 values.push({key: cursor.key, value: cursor.value});
jsbell 2012/07/27 00:25:46 Although the input/output stores here differ, havi
ericu 2012/07/31 01:00:53 Added a TODO to add a test that writes back to the
325 cursor.continue();
326 } else {
327 assert(!numReadsLeft);
328 }
329 }
330 request.onerror = onError;
331 }
332
333
241 function stringOfLength(n) { 334 function stringOfLength(n) {
242 assert(n > 0); 335 assert(n > 0);
243 assert(n == Math.floor(n)); 336 assert(n == Math.floor(n));
244 return new Array(n + 1).join('0'); 337 return new Array(n + 1).join('0');
245 } 338 }
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/indexeddb/perf_test.js » ('j') | chrome/test/data/indexeddb/perf_test.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698