tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 );