Commit a5c95824 authored by ericu@google.com's avatar ericu@google.com

Add IDB perf tests for random read, with and without an index.

BUG=137764
TEST=self

Review URL: https://chromiumcodereview.appspot.com/10790041

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148630 0039d316-1c4b-4281-b951-d872f2087c98
parent 15dd901f
...@@ -40,51 +40,65 @@ function assert(t) { ...@@ -40,51 +40,65 @@ function assert(t) {
} }
function onError(e) { function onError(e) {
console.log(e); var s = "Caught error.";
if (e.target && e.target.webkitErrorMessage)
s += "\n" + e.target.webkitErrorMessage;
console.log(s);
automation.setStatus(s);
e.stopPropagation(); e.stopPropagation();
throw new Error(e); throw new Error(e);
} }
var version = 2; // The version with our object stores. var version = 2; // The version with our object stores.
var db;
function createDatabase(name, objectStores, handler, errorHandler) { // Valid options fields:
// indexName: the name of an index to create on each object store
// indexKeyPath: likewise
// indexIsUnique: the "unique" option for IDBIndexParameters
// indexIsMultiEntry: the "multiEntry" option for IDBIndexParameters
//
function createDatabase(
name, objectStoreNames, handler, errorHandler, options) {
var openRequest = indexedDB.open(name, version); var openRequest = indexedDB.open(name, version);
openRequest.onblocked = errorHandler; openRequest.onblocked = errorHandler;
function createObjectStores(db) { function createObjectStores(db) {
for (var store in objectStores) { for (var store in objectStoreNames) {
var name = objectStores[store]; var name = objectStoreNames[store];
assert(!db.objectStoreNames.contains(name)); assert(!db.objectStoreNames.contains(name));
db.createObjectStore(name); var os = db.createObjectStore(name);
if (options && options.indexName) {
assert('indexKeyPath' in options);
os.createIndex(options.indexName, options.indexKeyPath,
{ unique: options.indexIsUnique,
multiEntry: options.indexIsMultiEntry });
}
} }
} }
openRequest.onupgradeneeded = function(ev) { openRequest.onupgradeneeded = function(ev) {
// TODO: This is the spec-compliant path, which doesn't yet work in Chrome, // TODO: This is the spec-compliant path, which doesn't yet work in Chrome,
// and isn't yet tested, as this function won't currently be called. // and isn't yet tested, as this function won't currently be called.
assert(openRequest == ev.target); assert(openRequest == ev.target);
db = openRequest.result; createObjectStores(openRequest.result);
createObjectStores(db);
// onsuccess will get called after this exits. // onsuccess will get called after this exits.
}; };
openRequest.onsuccess = function(ev) { openRequest.onsuccess = function(ev) {
assert(openRequest == ev.target); assert(openRequest == ev.target);
db = openRequest.result; var db = openRequest.result;
db.onerror = function(ev) { db.onerror = function(ev) {
console.log("db error", arguments, openRequest.webkitErrorMessage); console.log("db error", arguments, openRequest.webkitErrorMessage);
errorHandler(); errorHandler();
} };
if (db.version != version) { if (db.version != version) {
// This is the current Chrome path. // This is the current Chrome path.
var setVersionRequest = db.setVersion(version); var setVersionRequest = db.setVersion(version);
setVersionRequest.onfailure = errorHandler; setVersionRequest.onfailure = errorHandler;
setVersionRequest.onsuccess = setVersionRequest.onsuccess = function(e) {
function(e) {
assert(setVersionRequest == e.target); assert(setVersionRequest == e.target);
createObjectStores(db); createObjectStores(db);
var versionTransaction = setVersionRequest.result; var versionTransaction = setVersionRequest.result;
versionTransaction.oncomplete = function() {handler(db); }; versionTransaction.oncomplete = function() {handler(db); };
versionTransaction.onerror = onError; versionTransaction.onerror = onError;
} };
} else { } else {
handler(db); handler(db);
} }
...@@ -109,10 +123,19 @@ function deleteDatabase(name, opt_handler) { ...@@ -109,10 +123,19 @@ function deleteDatabase(name, opt_handler) {
} }
} }
function cleanUp(opt_handler) { function getCompletionFunc(testName, startTime, onTestComplete) {
if (db) { function onDeleted() {
deleteDatabase(db, opt_handler); automation.setStatus("Deleted database.");
db = null; onTestComplete();
}
return function() {
var duration = Date.now() - startTime;
// Ignore the cleanup time for this test.
automation.addResult(testName, duration);
automation.setStatus("Deleting database.");
// TODO: Turn on actual deletion; for now it's way too slow.
// deleteDatabase(testName, onDeleted);
onTestComplete();
} }
} }
......
...@@ -15,41 +15,123 @@ function testCreateKeysInStores( ...@@ -15,41 +15,123 @@ function testCreateKeysInStores(
objectStoreNames.push("store " + i); objectStoreNames.push("store " + i);
} }
var value = stringOfLength(payloadLength); var value = stringOfLength(payloadLength);
var start;
function onCreated(db) { function onCreated(db) {
automation.setStatus("Constructing transaction."); automation.setStatus("Constructing transaction.");
start = Date.now(); // Ignore the setup time for this test. var completionFunc =
getCompletionFunc(testName, Date.now(), onTestComplete);
var transaction = getTransaction(db, objectStoreNames, "readwrite", var transaction = getTransaction(db, objectStoreNames, "readwrite",
function() { onTransactionComplete(db); }); function() { completionFunc(); });
for (var i in objectStoreNames) { for (var i in objectStoreNames) {
var os = transaction.objectStore(objectStoreNames[i]); var os = transaction.objectStore(objectStoreNames[i]);
assert(os); assert(os);
for (var j = 0; j < numKeys; ++j) { for (var j = 0; j < numKeys; ++j) {
os.put("key " + j, value); os.put(value, "key " + j);
} }
} }
} }
function onTransactionComplete(db) { automation.setStatus("Creating database.");
var duration = Date.now() - start; createDatabase(testName, objectStoreNames, onCreated, onError);
// Ignore the cleanup time for this test. }
automation.addResult(testName, duration);
automation.setStatus("Deleting."); function testRandomReads(numKeys, numReadsPerTransaction, numTransactions,
deleteDatabase(db, onDeleted); useIndex, onTestComplete) {
var indexText = "_bare";
var indexName;
if (useIndex) {
indexText = "_index";
indexName = "index";
} }
function onDeleted() { var testName = "testRandomReads_" + numKeys + "_" + numReadsPerTransaction +
automation.setStatus("Deleted."); "_" + numTransactions + indexText;
onTestComplete(); var numTransactionsLeft = numTransactions;
var storeName = "store";
var objectStoreNames = [storeName];
var numTransactionsRunning;
function getKey(i) {
return "key " + i;
} }
automation.setStatus("Creating.");
createDatabase(testName, objectStoreNames, onCreated, onError); function getValue(i) {
return "value " + i;
}
function onCreated(db) {
automation.setStatus("Setting up test database.");
var transaction = getTransaction(db, objectStoreNames, "readwrite",
function() { onSetupComplete(db); });
var os = transaction.objectStore(storeName);
assert(os);
for (var j = 0; j < numKeys; ++j) {
os.put(getValue(i), getKey(j));
}
}
var completionFunc;
function onSetupComplete(db) {
automation.setStatus("Setup complete.");
runOneBatch(db);
completionFunc = getCompletionFunc(testName, Date.now(), onTestComplete);
}
function runOneBatch(db) {
if (numTransactionsLeft <= 0) {
return;
}
--numTransactionsLeft;
++numTransactionsRunning;
var valuesToRead = numReadsPerTransaction;
var transaction = getTransaction(db, objectStoreNames, "readonly",
function() {
assert(!--numTransactionsRunning);
assert(!valuesToRead);
if (numTransactionsLeft <= 0) {
completionFunc();
} else {
runOneBatch(db);
}
});
var queryObject = transaction.objectStore(storeName);
if (useIndex) {
queryObject = queryObject.index(indexName);
}
assert(queryObject);
for (var i = 0; i < numReadsPerTransaction; ++i) {
var rand = Math.floor(Math.random() * numKeys);
var request = queryObject.get(getKey(rand));
request.onerror = onError;
request.onsuccess = function () {
assert(valuesToRead--);
}
}
}
automation.setStatus("Creating database.");
var options = {};
if (useIndex) {
options.indexName = indexName;
options.indexKeyPath = "";
options.indexIsUnique = true;
options.indexIsMultiEntry = false;
}
createDatabase(testName, objectStoreNames, onCreated, onError, options);
} }
var kUseIndex = true;
var kDontUseIndex = false;
var tests = [ var tests = [
[testCreateKeysInStores, 1, 1, 1], [testCreateKeysInStores, 1, 1, 1],
[testCreateKeysInStores, 100, 1, 1], [testCreateKeysInStores, 100, 1, 1],
[testCreateKeysInStores, 1, 100, 1], [testCreateKeysInStores, 1, 100, 1],
[testCreateKeysInStores, 100, 1, 100000] [testCreateKeysInStores, 100, 1, 10000],
[testRandomReads, 1000, 5, 50, kDontUseIndex],
[testRandomReads, 1000, 50, 5, kDontUseIndex],
[testRandomReads, 5000, 50, 5, kDontUseIndex],
[testRandomReads, 1000, 5, 50, kUseIndex],
[testRandomReads, 1000, 50, 5, kUseIndex],
[testRandomReads, 5000, 50, 5, kUseIndex]
]; ];
var currentTest = 0; var currentTest = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment