indexeddb_write.js (5419B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* eslint-env node */ 6 7 const { logTest } = require("./utils/profiling"); 8 9 module.exports = logTest( 10 "indexedDB write test", 11 async function (context, commands) { 12 context.log.info("Starting a indexedDB write"); 13 const post_startup_delay = context.options.browsertime.post_startup_delay; 14 console.log("context options", context.options); 15 16 const test_url = context.options.browsertime.url; 17 const chunk_size = context.options.browsertime.chunk_size; 18 const iterations = context.options.browsertime.iterations; 19 const buffer_type = context.options.browsertime.buffer_type; 20 const atomic_value = context.options.browsertime.atomic; 21 if (atomic_value * atomic_value != atomic_value) { 22 throw Error("Value of atomic shall be 0 for falsehood, 1 for truth."); 23 } 24 const atomic = 0 != atomic_value; 25 26 const accepted_buffers = ["Array", "ArrayBuffer", "Blob"]; 27 if (!accepted_buffers.includes(buffer_type)) { 28 throw Error("Buffer type " + buffer_type + " is unknown."); 29 } 30 31 context.log.info("IndexedDB write URL = " + test_url); 32 context.log.info("IndexedDB write chunk size = " + chunk_size); 33 context.log.info("IndexedDB write iterations = " + iterations); 34 context.log.info( 35 "IndexedDB writes " + 36 (atomic ? "all in one big transaction" : "in separate transactions") 37 ); 38 context.log.info("IndexedDB write data format " + buffer_type); 39 40 context.log.info( 41 "Waiting for %d ms (post_startup_delay)", 42 post_startup_delay 43 ); 44 45 await commands.navigate(test_url); 46 47 const seleniumDriver = context.selenium.driver; 48 49 await commands.wait.byTime(post_startup_delay); 50 51 await commands.measure.start(); 52 const time_duration = await seleniumDriver.executeAsyncScript(` 53 const notifyDone = arguments[arguments.length - 1]; 54 55 const iterations = ${iterations}; 56 const sizeInBytes = ${chunk_size}; 57 const bufferType = "${buffer_type}"; 58 const atomic = ${atomic}; 59 60 const makeData = (() => { 61 if (bufferType === "ArrayBuffer") { 62 return () => { 63 const valueBuffer = new ArrayBuffer(sizeInBytes); 64 65 const charCodeView = new Uint16Array(valueBuffer); 66 const sizeInUint16 = sizeInBytes / 2; 67 for (let i=0; i < sizeInUint16; ++i) { 68 charCodeView[i] = "qwerty".charCodeAt(i % 6); 69 } 70 71 return valueBuffer; 72 }; 73 } 74 75 if (bufferType === "Array") { 76 return () => { 77 return Array.from({length: sizeInBytes}, (_, i) => "qwerty"[i % 6]); 78 }; 79 } 80 81 if (bufferType !== "Blob") { 82 throw Error("Unknown buffer type " + bufferType); 83 } 84 85 return () => { 86 return new Blob([Array.from({length: sizeInBytes}, (_, i) => "qwerty"[i % 6])]); 87 }; 88 })(); 89 90 function addData(txSource, txProvider, i) { 91 try { 92 const keyName = "doc_" + i; 93 const valueData = makeData(); 94 const record = { key: keyName, property: valueData }; 95 96 const rq = txProvider(txSource).add(record); 97 98 return new Promise((res_ad, rej_ad) => { 99 rq.onsuccess = () => { res_ad(); }; 100 rq.onerror = e => { rej_ad(e); }; 101 }); 102 } catch (e) { 103 return new Promise((_, rej_ad) => rej_ad(e)); 104 } 105 } 106 107 function waitForData(txSource) { 108 try { 109 if (!atomic) { 110 const txProvider = src => src.transaction("store", "readwrite").objectStore("store"); 111 return Promise.all( 112 Array.from({ length: iterations }, (_, i) => { 113 return addData(txSource, txProvider, i); 114 })); 115 } 116 117 const currentTx = txSource.transaction("store", "readwrite").objectStore("store"); 118 return Promise.all( 119 Array.from({ length: iterations }, (_, i) => { 120 return addData(currentTx, src => src, i); 121 })); 122 } catch (e) { 123 return new Promise((_, rej_tx) => rej_tx(e)); 124 } 125 } 126 127 function upgradePromise() { 128 try { 129 const open_db = indexedDB.open("rootsdb"); 130 return new Promise((res_upgrade, rej_upgrade) => { 131 open_db.onupgradeneeded = e => { 132 e.target.result.createObjectStore("store", { keyPath: "key" }); 133 }; 134 open_db.onsuccess = e => { res_upgrade(e.target.result); }; 135 open_db.onerror = e => { rej_upgrade(e); }; 136 }); 137 } catch (e) { 138 return new Promise((_, rej_upgrade) => rej_upgrade(e)); 139 } 140 } 141 142 const startTime = performance.now(); 143 upgradePromise().then(waitForData).then(() => { 144 notifyDone(performance.now() - startTime); 145 }); 146 `); 147 await commands.measure.stop(); 148 149 console.log("Time duration was ", time_duration); 150 151 await commands.measure.addObject({ 152 custom_data: { time_duration }, 153 }); 154 155 context.log.info("IndexedDB write ended."); 156 return true; 157 } 158 );