summaryrefslogtreecommitdiffstats
path: root/tools/page_cycler/database
diff options
context:
space:
mode:
authordumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-29 23:27:37 +0000
committerdumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-29 23:27:37 +0000
commit81545760b52a29fbcc7a594b5b81fd1d7cdcf8ec (patch)
tree3b750fc0c9508b4eff5b9729e7e0613bb4328cb1 /tools/page_cycler/database
parent35f2094cd0ac27018aff2646445f44c3f9ee8d36 (diff)
downloadchromium_src-81545760b52a29fbcc7a594b5b81fd1d7cdcf8ec.zip
chromium_src-81545760b52a29fbcc7a594b5b81fd1d7cdcf8ec.tar.gz
chromium_src-81545760b52a29fbcc7a594b5b81fd1d7cdcf8ec.tar.bz2
Adding the DB performance tests.
BUG=none TEST=none Review URL: http://codereview.chromium.org/465141 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35355 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/page_cycler/database')
-rw-r--r--tools/page_cycler/database/common.js109
-rw-r--r--tools/page_cycler/database/delete-transactions/index.html26
-rw-r--r--tools/page_cycler/database/delete-transactions/start.html9
-rw-r--r--tools/page_cycler/database/head.js120
-rw-r--r--tools/page_cycler/database/insert-transactions/index.html28
-rw-r--r--tools/page_cycler/database/insert-transactions/start.html9
-rw-r--r--tools/page_cycler/database/pseudo-random-transactions/index.html103
-rw-r--r--tools/page_cycler/database/pseudo-random-transactions/start.html9
-rw-r--r--tools/page_cycler/database/select-readtransactions-read-results/index.html33
-rw-r--r--tools/page_cycler/database/select-readtransactions-read-results/start.html9
-rw-r--r--tools/page_cycler/database/select-readtransactions/index.html26
-rw-r--r--tools/page_cycler/database/select-readtransactions/start.html9
-rw-r--r--tools/page_cycler/database/select-transactions/index.html25
-rw-r--r--tools/page_cycler/database/select-transactions/start.html9
-rw-r--r--tools/page_cycler/database/start.js58
-rw-r--r--tools/page_cycler/database/update-transactions/index.html28
-rw-r--r--tools/page_cycler/database/update-transactions/start.html9
17 files changed, 619 insertions, 0 deletions
diff --git a/tools/page_cycler/database/common.js b/tools/page_cycler/database/common.js
new file mode 100644
index 0000000..75c50e4
--- /dev/null
+++ b/tools/page_cycler/database/common.js
@@ -0,0 +1,109 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A collection of common functions used by all database
+ * performance tests.
+ */
+
+var CANNOT_OPEN_DB = -1;
+var SETUP_FAILED = -2;
+var TEST_FAILED = -3;
+
+var TRANSACTIONS = 1000; // number of transactions; number of rows in the DB
+var RANDOM_STRING_LENGTH = 20; // the length of the string on each row
+
+/**
+ * Generates a random string of upper-case letters of
+ * RANDOM_STRING_LENGTH length.
+ */
+function getRandomString() {
+ var s = '';
+ for (var i = 0; i < RANDOM_STRING_LENGTH; i++)
+ s += String.fromCharCode(Math.floor(Math.random() * 26) + 64);
+ return s;
+}
+
+/**
+ * Sets up and runs a performance test.
+ * @param {!Object} params An object which must have the following fields:
+ * dbName: The database name.
+ * readOnly: If true, transactions will be run using the readTransaction()
+ * method. Otherwise, transaction() will be used.
+ * insertRowsAtSetup: Determines if setting up the database should include
+ * inserting TRANSACTIONS rows in it.
+ * transactionCallback: The transaction callback that should be timed. This
+ * function will be run TRANSACTIONS times and must take a transaction
+ * object as its only parameter.
+ * customRunTransactions: A custom function for running and timing
+ * transactions. If this parameter is not null, runPerformanceTest() will
+ * ignore the txFnct parameter and will call customRunTransactions() as
+ * soon as the setup is complete. In this case, the user is responsible
+ * for running and timing the transactions. If not null, this parameter
+ * must be a function that takes a database object as its only parameter.
+ */
+function runPerformanceTest(params) {
+ var db = openTestDatabase(params.dbName);
+ if (!db) {
+ testComplete(CANNOT_OPEN_DB);
+ return;
+ }
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE Test (ID INT, Foo TEXT)', [],
+ function(tx, data) {}, function(tx, error) {});
+ tx.executeSql('DELETE FROM Test');
+ if (params.insertRowsAtSetup) {
+ var randomString = getRandomString();
+ for (var i = 0; i < TRANSACTIONS; i++) {
+ tx.executeSql('INSERT INTO Test VALUES (?, ?)',
+ [i, randomString]);
+ }
+ }
+ }, function(error) {
+ testComplete(SETUP_FAILED);
+ }, function() {
+ if (params.customRunTransactions)
+ params.customRunTransactions(db);
+ else
+ runTransactions(db, params.readOnly, params.transactionCallback);
+ });
+}
+
+/**
+ * Opens a database with the given name.
+ * @param {string} name The name of the database.
+ */
+function openTestDatabase(name) {
+ if (window.openDatabase) {
+ return window.openDatabase(name, '1.0', 'Test database.',
+ TRANSACTIONS * RANDOM_STRING_LENGTH);
+ }
+
+ return null;
+}
+
+/**
+ * Runs the given transaction TRANSACTIONS times.
+ * @param {!Object} db The database to run transactions on.
+ * @param {boolean} readOnly If true, all transactions will be run using the
+ * db.readTransaction() call. Otherwise, the transactions will be run
+ * using the db.transaction() call.
+ * @param {function(!Object)} The transaction callback.
+ */
+function runTransactions(db, readOnly, transactionCallback) {
+ var transactionsCompleted = 0;
+ var transactionFunction = readOnly ? db.readTransaction : db.transaction;
+ var startTime = Date.now();
+ for (var i = 0; i < TRANSACTIONS; i++) {
+ transactionFunction.call(db, transactionCallback,
+ function(error) {
+ testComplete(TEST_FAILED);
+ }, function() {
+ if (++transactionsCompleted == TRANSACTIONS)
+ testComplete(Date.now() - startTime);
+ });
+ }
+}
diff --git a/tools/page_cycler/database/delete-transactions/index.html b/tools/page_cycler/database/delete-transactions/index.html
new file mode 100644
index 0000000..b5e5651
--- /dev/null
+++ b/tools/page_cycler/database/delete-transactions/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<title>Delete transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('DELETE FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "DeleteTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/delete-transactions/start.html b/tools/page_cycler/database/delete-transactions/start.html
new file mode 100644
index 0000000..596e60c
--- /dev/null
+++ b/tools/page_cycler/database/delete-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=delete-transactions; path=/";</script>
+<script src="../start.js"></script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/head.js b/tools/page_cycler/database/head.js
new file mode 100644
index 0000000..fedacec
--- /dev/null
+++ b/tools/page_cycler/database/head.js
@@ -0,0 +1,120 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var totalTime;
+var fudgeTime;
+var elapsedTime;
+var endTime;
+var iterations;
+var cycle;
+var results = false;
+var TIMEOUT = 15;
+
+/**
+ * Returns the value of the given property stored in the cookie.
+ * @param {string} name The property name.
+ * @return {string} The value of the given property, or empty string
+ * if the property was not found.
+ */
+function getPropertyValue(name) {
+ var cookies = document.cookie.split('; ');
+ for (var i = 0; i < cookies.length; ++i) {
+ var t = cookies[i].split('=');
+ if ((t[0] == name) && t[1])
+ return t[1];
+ }
+ return '';
+}
+
+/**
+ * Returns the value of the '__pc_timings' property.
+ * @return {string} The list of all timings we got so far.
+ */
+function getTimings() {
+ return getPropertyValue('__pc_timings');
+}
+
+/**
+ * Sets the value of the '__pc_timings' property in the cookie.
+ * @param {string} timings A comma-separated list of timings.
+ */
+function setTimings(timings) {
+ document.cookie = '__pc_timings=' + timings + '; path=/';
+}
+
+/**
+ * Starts the next test cycle or redirects the browser to the results page.
+ */
+function nextCycleOrResults() {
+ // Call GC twice to cleanup JS heap before starting a new test.
+ if (window.gc) {
+ window.gc();
+ window.gc();
+ }
+
+ var tLag = Date.now() - endTime - TIMEOUT;
+ if (tLag > 0)
+ fudgeTime += tLag;
+
+ var doc;
+ if (cycle == iterations) {
+ document.cookie = '__pc_done=1; path=/';
+ doc = '../../common/report.html';
+ } else {
+ doc = 'index.html';
+ }
+
+ var timings = elapsedTime;
+ var oldTimings = getTimings();
+ if (oldTimings != '')
+ timings = oldTimings + ',' + timings;
+ setTimings(timings);
+
+ var url = doc + '?n=' + iterations + '&i=' + cycle +
+ '&td=' + totalTime + '&tf=' + fudgeTime;
+ document.location.href = url;
+}
+
+/**
+ * Computes various running times and updates the stats reported at the end.
+ * @param {!number} cycleTime The running time of the test cycle.
+ */
+function testComplete(cycleTime) {
+ if (results)
+ return;
+
+ var oldTotalTime = 0;
+ var cycleEndTime = Date.now();
+ var cycleFudgeTime = 0;
+
+ var s = document.location.search;
+ if (s) {
+ var params = s.substring(1).split('&');
+ for (var i = 0; i < params.length; i++) {
+ var f = params[i].split('=');
+ switch (f[0]) {
+ case 'skip':
+ return; // No calculation, just viewing
+ case 'n':
+ iterations = f[1];
+ break;
+ case 'i':
+ cycle = f[1] - 0 + 1;
+ break;
+ case 'td':
+ oldTotalTime = f[1] - 0;
+ break;
+ case 'tf':
+ cycleFudgeTime = f[1] - 0;
+ break;
+ }
+ }
+ }
+ elapsedTime = cycleTime;
+ totalTime = oldTotalTime + elapsedTime;
+ endTime = cycleEndTime;
+ fudgeTime = cycleFudgeTime;
+
+ setTimeout(nextCycleOrResults, TIMEOUT);
+}
diff --git a/tools/page_cycler/database/insert-transactions/index.html b/tools/page_cycler/database/insert-transactions/index.html
new file mode 100644
index 0000000..f17b977
--- /dev/null
+++ b/tools/page_cycler/database/insert-transactions/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<title>Insert transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var randomString = getRandomString();
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('INSERT INTO Test VALUES (?, ?)',
+ [idCounter++, randomString],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "InsertTransactions",
+ readOnly: false,
+ insertRowsAtSetup: false,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/insert-transactions/start.html b/tools/page_cycler/database/insert-transactions/start.html
new file mode 100644
index 0000000..f8538de
--- /dev/null
+++ b/tools/page_cycler/database/insert-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=insert-transactions; path=/";</script>
+<script src="../start.js"></script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/pseudo-random-transactions/index.html b/tools/page_cycler/database/pseudo-random-transactions/index.html
new file mode 100644
index 0000000..3732bce
--- /dev/null
+++ b/tools/page_cycler/database/pseudo-random-transactions/index.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<title>Pseudo-random transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var SELECT_STATEMENT_IN_READ_TRANSACTION = 0;
+var SELECT_STATEMENT_IN_TRANSACTION = 1;
+var INSERT_STATEMENT = 2;
+var UPDATE_STATEMENT = 3;
+var DELETE_STATEMENT = 4;
+var STATEMENTS =
+ [2, 0, 4, 2, 2, 2, 2, 2, 1, 4, 1, 1, 0, 2, 0, 0, 2, 1, 2, 0,
+ 4, 4, 2, 3, 3, 4, 3, 1, 3, 3, 2, 4, 3, 3, 2, 3, 1, 1, 4, 2,
+ 4, 1, 4, 2, 3, 0, 4, 2, 4, 0, 4, 3, 3, 2, 0, 2, 1, 4, 4, 4,
+ 4, 2, 3, 2, 0, 3, 3, 0, 4, 4, 4, 2, 3, 1, 4, 2, 4, 2, 3, 0,
+ 2, 4, 0, 4, 2, 2, 4, 0, 3, 2, 3, 2, 3, 2, 0, 0, 4, 0, 2, 0];
+
+var transactionsCompleted = 0;
+var startTime = 0;
+
+function statementSuccessCallback(tx, data) {}
+function statementErrorCallback(tx, error) {}
+
+function transactionSuccessCallback() {
+ if (++transactionsCompleted == TRANSACTIONS)
+ testComplete(Date.now() - startTime);
+}
+
+function transactionErrorCallback(error) {
+ testComplete(TEST_FAILED);
+}
+
+function customRunTransactions(db) {
+ var selectIDCounter = 0;
+ var insertIDCounter = 0;
+ var updateIDCounter = 0;
+ var deleteIDCounter = 0;
+ var randomString = getRandomString();
+ var randomStringForUpdates = getRandomString();
+ startTime = Date.now();
+ for (var i = 0; i < TRANSACTIONS; i++) {
+ switch (STATEMENTS[i % STATEMENTS.length]) {
+ case SELECT_STATEMENT_IN_READ_TRANSACTION:
+ db.readTransaction(
+ function(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?',
+ [selectIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case SELECT_STATEMENT_IN_TRANSACTION:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?',
+ [selectIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case INSERT_STATEMENT:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('INSERT INTO Test VALUES (?, ?)',
+ [insertIDCounter++, randomString],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case UPDATE_STATEMENT:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('UPDATE Test SET Foo = ? WHERE ID = ?',
+ [randomStringForUpdates, updateIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case DELETE_STATEMENT:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('DELETE FROM Test WHERE ID = ?',
+ [deleteIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ default:
+ testComplete(TEST_FAILED);
+ return;
+ }
+ }
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "PseudoRandomTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: null,
+ customRunTransactions: customRunTransactions
+ });
+</script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/pseudo-random-transactions/start.html b/tools/page_cycler/database/pseudo-random-transactions/start.html
new file mode 100644
index 0000000..6278291
--- /dev/null
+++ b/tools/page_cycler/database/pseudo-random-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=pseudo-random-transactions; path=/";</script>
+<script src="../start.js"></script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/select-readtransactions-read-results/index.html b/tools/page_cycler/database/select-readtransactions-read-results/index.html
new file mode 100644
index 0000000..40a2d87
--- /dev/null
+++ b/tools/page_cycler/database/select-readtransactions-read-results/index.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<title>Select read-transactions (store results in JS variables)</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+var resultId = 0;
+var resultString = '';
+
+function transactionCallback(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {
+ for (var i = 0; i < data.rows.length; i++) {
+ resultId = data.rows.item(i).ID;
+ resultString = data.rows.item(i).Foo;
+ }
+ }, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "SelectReadTransactionsReadResults",
+ readOnly: true,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/select-readtransactions-read-results/start.html b/tools/page_cycler/database/select-readtransactions-read-results/start.html
new file mode 100644
index 0000000..bbb0aef
--- /dev/null
+++ b/tools/page_cycler/database/select-readtransactions-read-results/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=select-readtransactions-read-results; path=/";</script>
+<script src="../start.js"></script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/select-readtransactions/index.html b/tools/page_cycler/database/select-readtransactions/index.html
new file mode 100644
index 0000000..e923bc2
--- /dev/null
+++ b/tools/page_cycler/database/select-readtransactions/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<title>Select read-transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "SelectReadTransactions",
+ readOnly: true,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/select-readtransactions/start.html b/tools/page_cycler/database/select-readtransactions/start.html
new file mode 100644
index 0000000..6833f1b
--- /dev/null
+++ b/tools/page_cycler/database/select-readtransactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=select-readtransactions; path=/";</script>
+<script src="../start.js"></script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/select-transactions/index.html b/tools/page_cycler/database/select-transactions/index.html
new file mode 100644
index 0000000..bfd0b39
--- /dev/null
+++ b/tools/page_cycler/database/select-transactions/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<title>Select transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "SelectTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });</script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/select-transactions/start.html b/tools/page_cycler/database/select-transactions/start.html
new file mode 100644
index 0000000..ce9d2e9
--- /dev/null
+++ b/tools/page_cycler/database/select-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=select-transactions; path=/";</script>
+<script src="../start.js"></script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/start.js b/tools/page_cycler/database/start.js
new file mode 100644
index 0000000..c3da326
--- /dev/null
+++ b/tools/page_cycler/database/start.js
@@ -0,0 +1,58 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+document.title = 'page cycler';
+
+document.cookie = '__pc_done=0; path=/';
+document.cookie = '__pc_timings=; path=/';
+
+var options = location.search.substring(1).split('&');
+
+function getOption(name) {
+ var r = new RegExp('^' + name + '=');
+ for (var i = 0; i < options.length; i++) {
+ if (options[i].match(r)) {
+ return options[i].substring(name.length + 1);
+ }
+ }
+ return null;
+}
+
+function start() {
+ var iterations = document.getElementById('iterations').value;
+ window.resizeTo(800, 800);
+ var url = 'index.html?n=' + iterations + '&i=0&td=0';
+ window.location = url;
+}
+
+function renderForm() {
+ var form = document.createElement('form');
+ form.onsubmit = function(e) {
+ start();
+ e.preventDefault();
+ };
+
+ var label = document.createTextNode('Iterations: ');
+ form.appendChild(label);
+
+ var input = document.createElement('input');
+ input.id = 'iterations';
+ input.type = 'number';
+ var iterations = getOption('iterations');
+ input.value = iterations ? iterations : '5';
+ form.appendChild(input);
+
+ input = document.createElement('input');
+ input.type = 'submit';
+ input.value = 'Start';
+ form.appendChild(input);
+
+ document.body.appendChild(form);
+}
+
+renderForm();
+
+// should we start automatically?
+if (location.search.match('auto=1'))
+ start();
diff --git a/tools/page_cycler/database/update-transactions/index.html b/tools/page_cycler/database/update-transactions/index.html
new file mode 100644
index 0000000..75d3c57
--- /dev/null
+++ b/tools/page_cycler/database/update-transactions/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<title>Update transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var randomString = getRandomString();
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('UPDATE Test SET Foo = ? WHERE ID = ?',
+ [randomString, idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "UpdateTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/tools/page_cycler/database/update-transactions/start.html b/tools/page_cycler/database/update-transactions/start.html
new file mode 100644
index 0000000..2c2e2a0
--- /dev/null
+++ b/tools/page_cycler/database/update-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=update-transactions; path=/";</script>
+<script src="../start.js"></script>
+</body>
+</html>