From 539174891db05b4cb099d417e7b3a27cf770902b Mon Sep 17 00:00:00 2001 From: Andrei Kalfas Date: Wed, 26 Jun 2024 11:55:56 +0300 Subject: [PATCH 1/6] fix(rum-explorer) use a cached value of the conversion spec --- tools/rum/utils.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/rum/utils.js b/tools/rum/utils.js index 0ea76898..5f6a2777 100644 --- a/tools/rum/utils.js +++ b/tools/rum/utils.js @@ -195,11 +195,14 @@ export function parseSearchParams(params, filterFn, transformFn) { return acc; }, {}); } +const cached = {}; export function parseConversionSpec() { + if (cached.conversionSpec) return cached.conversionSpec; const params = new URL(window.location).searchParams; const transform = ([key, value]) => [key.replace('conversion.', ''), value]; const filter = ([key]) => (key.startsWith('conversion.')); - return parseSearchParams(params, filter, transform); + cached.conversionSpec = parseSearchParams(params, filter, transform); + return cached.conversionSpec; } /** From dd7ec17c73e424e36568cfa9346e87f8b2839567 Mon Sep 17 00:00:00 2001 From: Andrei Kalfas Date: Wed, 26 Jun 2024 14:31:35 +0300 Subject: [PATCH 2/6] fix(rum-explorer) use loops instead of reduce for tTest --- tools/rum/cruncher.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/rum/cruncher.js b/tools/rum/cruncher.js index 9155404e..8089437f 100644 --- a/tools/rum/cruncher.js +++ b/tools/rum/cruncher.js @@ -234,6 +234,26 @@ function erf(x1) { return sign * y; } +function compute(data) { + let sum = 0; + let variance = 0; + + // Calculate sum + for (let i = 0; i < data.length; i += 1) { + sum += data[i]; + } + + const mean = sum / data.length; + + // Calculate variance + for (let i = 0; i < data.length; i += 1) { + variance += (data[i] - mean) ** 2; + } + + variance /= data.length; + + return { mean, variance }; +} /** * Performs a significance test on the data. The test assumes * that the data is normally distributed and will calculate @@ -243,11 +263,8 @@ function erf(x1) { * @returns {number} the p-value, a value between 0 and 1 */ export function tTest(left, right) { - const meanLeft = left.reduce((acc, value) => acc + value, 0) / left.length; - const meanRight = right.reduce((acc, value) => acc + value, 0) / right.length; - const varianceLeft = left.reduce((acc, value) => acc + (value - meanLeft) ** 2, 0) / left.length; - const varianceRight = right - .reduce((acc, value) => acc + (value - meanRight) ** 2, 0) / right.length; + const { mean: meanLeft, variance: varianceLeft } = compute(left); + const { mean: meanRight, variance: varianceRight } = compute(right); const pooledVariance = (varianceLeft + varianceRight) / 2; const tValue = (meanLeft - meanRight) / Math .sqrt(pooledVariance * (1 / left.length + 1 / right.length)); From 6c70247868f2b23f808b5f8a0a8fcf757612a439 Mon Sep 17 00:00:00 2001 From: Andrei Kalfas Date: Mon, 1 Jul 2024 12:05:21 +0300 Subject: [PATCH 3/6] fix(rum-explorer) cache network calls to bundles --- tools/rum/loader.js | 27 +++++++++++++++++++++------ tools/rum/slicer.js | 1 + 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/tools/rum/loader.js b/tools/rum/loader.js index e284eff0..b618cd70 100644 --- a/tools/rum/loader.js +++ b/tools/rum/loader.js @@ -7,14 +7,18 @@ import { addCalculatedProps } from './cruncher.js'; export default class DataLoader { constructor() { - this.cache = new Map(); this.API_ENDPOINT = 'https://rum.fastly-aem.page/bundles'; this.DOMAIN = 'www.thinktanked.org'; this.DOMAIN_KEY = ''; } - flush() { - this.cache.clear(); + async init() { + this.cache = await caches.open('bundles'); + } + + async flush() { + await caches.delete('bundles'); + this.cache = await caches.open('bundles'); } set domainKey(key) { @@ -46,13 +50,24 @@ export default class DataLoader { return u.toString(); } + async fetchBundles(apiRequestURL) { + const cacheResponse = await this.cache.match(apiRequestURL); + if (cacheResponse) { + return cacheResponse; + } + const networkResponse = await fetch(apiRequestURL); + const networkResponseClone = networkResponse.clone(); + this.cache.put(apiRequestURL, networkResponseClone); + return networkResponse; + } + async fetchUTCMonth(utcISOString) { const [date] = utcISOString.split('T'); const dateSplits = date.split('-'); dateSplits.pop(); const monthPath = dateSplits.join('/'); const apiRequestURL = this.apiURL(monthPath); - const resp = await fetch(apiRequestURL); + const resp = await this.fetchBundles(apiRequestURL); const json = await resp.json(); const { rumBundles } = json; rumBundles.forEach((bundle) => addCalculatedProps(bundle)); @@ -63,7 +78,7 @@ export default class DataLoader { const [date] = utcISOString.split('T'); const datePath = date.split('-').join('/'); const apiRequestURL = this.apiURL(datePath); - const resp = await fetch(apiRequestURL); + const resp = await this.fetchBundles(apiRequestURL); const json = await resp.json(); const { rumBundles } = json; rumBundles.forEach((bundle) => addCalculatedProps(bundle)); @@ -75,7 +90,7 @@ export default class DataLoader { const datePath = date.split('-').join('/'); const hour = time.split(':')[0]; const apiRequestURL = this.apiURL(datePath, hour); - const resp = await fetch(apiRequestURL); + const resp = await this.fetchBundles(apiRequestURL); const json = await resp.json(); const { rumBundles } = json; rumBundles.forEach((bundle) => addCalculatedProps(bundle)); diff --git a/tools/rum/slicer.js b/tools/rum/slicer.js index 1309514e..24b8d4fc 100644 --- a/tools/rum/slicer.js +++ b/tools/rum/slicer.js @@ -24,6 +24,7 @@ const elems = {}; const dataChunks = new DataChunks(); const loader = new DataLoader(); +await loader.init(); loader.apiEndpoint = API_ENDPOINT; const herochart = new window.slicer.Chart(dataChunks, elems); From 53d56452aff3062754f23033dc0cf2d8c7d6cc57 Mon Sep 17 00:00:00 2001 From: Andrei Kalfas Date: Mon, 1 Jul 2024 12:32:51 +0300 Subject: [PATCH 4/6] fix(rum-explorer) no need to iterate over all events --- tools/rum/cruncher.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/rum/cruncher.js b/tools/rum/cruncher.js index 8089437f..5a826550 100644 --- a/tools/rum/cruncher.js +++ b/tools/rum/cruncher.js @@ -48,24 +48,30 @@ * @returns {Bundle} a bundle with additional properties */ export function addCalculatedProps(bundle) { - bundle.events.forEach((e) => { + for (let i = 0; i < bundle.events.length; i += 1) { + const e = bundle.events[i]; if (e.checkpoint === 'enter') { bundle.visit = true; if (e.source === '') e.source = '(direct)'; + break; } if (e.checkpoint === 'cwv-inp') { bundle.cwvINP = e.value; + break; } if (e.checkpoint === 'cwv-lcp') { bundle.cwvLCP = Math.max(e.value || 0, bundle.cwvLCP || 0); + break; } if (e.checkpoint === 'cwv-cls') { bundle.cwvCLS = Math.max(e.value || 0, bundle.cwvCLS || 0); + break; } if (e.checkpoint === 'cwv-ttfb') { bundle.cwvTTFB = e.value; + break; } - }); + } return bundle; } From b8e72a42c655ebf38448f687855e7bc5b6ba2e6f Mon Sep 17 00:00:00 2001 From: Andrei Kalfas Date: Tue, 2 Jul 2024 17:14:19 +0300 Subject: [PATCH 5/6] fix(rum-explorer) keep cached between views --- tools/rum/loader.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/rum/loader.js b/tools/rum/loader.js index b618cd70..f053e8ae 100644 --- a/tools/rum/loader.js +++ b/tools/rum/loader.js @@ -16,9 +16,10 @@ export default class DataLoader { this.cache = await caches.open('bundles'); } + // eslint-disable-next-line class-methods-use-this async flush() { - await caches.delete('bundles'); - this.cache = await caches.open('bundles'); + // await caches.delete('bundles'); + // this.cache = await caches.open('bundles'); } set domainKey(key) { From 70e58c9fb3f6672f58d993a3e5a30c70fe20d846 Mon Sep 17 00:00:00 2001 From: Andrei Kalfas Date: Tue, 2 Jul 2024 17:17:52 +0300 Subject: [PATCH 6/6] feat(rum-explorer) use wasm heavy data crunching --- tools/rum/cruncher.js | 16 ++++ tools/rum/elements/list-facet.js | 4 +- tools/rum/enigma.js | 129 +++++++++++++++++++++++++++++++ tools/rum/enigma_bg.wasm | Bin 0 -> 14746 bytes tools/rum/package.json | 19 +++-- 5 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 tools/rum/enigma.js create mode 100644 tools/rum/enigma_bg.wasm diff --git a/tools/rum/cruncher.js b/tools/rum/cruncher.js index 5a826550..36303a46 100644 --- a/tools/rum/cruncher.js +++ b/tools/rum/cruncher.js @@ -3,6 +3,10 @@ * filtering, aggregating, and summarizing the data. */ /* eslint-disable max-classes-per-file */ +// eslint-disable-next-line camelcase +import init, { t_test } from './enigma.js'; + +await init(); /** * @typedef {Object} RawEvent - a raw RUM event * @property {string} checkpoint - the name of the event that happened @@ -278,6 +282,18 @@ export function tTest(left, right) { return p; } +/** + * Performs a significance test on the data. The test assumes + * that the data is normally distributed and will calculate + * the p-value for the difference between the two data sets. + * @param {number[]} left the first data set + * @param {number[]} right the second data set + * @returns {number} the p-value, a value between 0 and 1 + */ +export function tTestWasm(left, right) { + return t_test(new Uint32Array(left), new Uint32Array(right)); +} + class Facet { constructor(parent, value, name) { this.parent = parent; diff --git a/tools/rum/elements/list-facet.js b/tools/rum/elements/list-facet.js index bdadff87..3a24f76a 100644 --- a/tools/rum/elements/list-facet.js +++ b/tools/rum/elements/list-facet.js @@ -1,13 +1,13 @@ import { computeConversionRate, escapeHTML, scoreCWV, toHumanReadable, } from '../utils.js'; -import { tTest, zTestTwoProportions } from '../cruncher.js'; +import { tTestWasm, zTestTwoProportions } from '../cruncher.js'; async function addSignificanceFlag(element, metric, baseline) { let p = 1; if (Array.isArray(metric.values) && Array.isArray(baseline.values)) { // for two arrays of values, we use a t-test - p = tTest(metric.values, baseline.values); + p = tTestWasm(metric.values, baseline.values); } else if ( typeof metric.total === 'number' && typeof metric.conversions === 'number' diff --git a/tools/rum/enigma.js b/tools/rum/enigma.js new file mode 100644 index 00000000..0887fe06 --- /dev/null +++ b/tools/rum/enigma.js @@ -0,0 +1,129 @@ +let wasm; + +let cachedUint32Memory0 = null; + +function getUint32Memory0() { + if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) { + cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32Memory0; +} + +let WASM_VECTOR_LEN = 0; + +function passArray32ToWasm0(arg, malloc) { + // eslint-disable-next-line no-bitwise + const ptr = malloc(arg.length * 4, 4) >>> 0; + getUint32Memory0().set(arg, ptr / 4); + WASM_VECTOR_LEN = arg.length; + return ptr; +} +/** +* @param {Uint32Array} left +* @param {Uint32Array} right +* @returns {number} +*/ +// eslint-disable-next-line camelcase +export function t_test(left, right) { + // eslint-disable-next-line no-underscore-dangle + const ptr0 = passArray32ToWasm0(left, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + // eslint-disable-next-line no-underscore-dangle + const ptr1 = passArray32ToWasm0(right, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.t_test(ptr0, len0, ptr1, len1); + return ret; +} + +// eslint-disable-next-line camelcase,no-underscore-dangle +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + } catch (e) { + if (module.headers.get('Content-Type') !== 'application/wasm') { + console.warn('`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n', e); + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + // eslint-disable-next-line no-return-await + return await WebAssembly.instantiate(bytes, imports); + } + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + } + return instance; +} + +// eslint-disable-next-line camelcase,no-underscore-dangle +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + + return imports; +} + +// eslint-disable-next-line no-underscore-dangle,camelcase,no-unused-vars +function __wbg_init_memory(imports, maybe_memory) { + +} + +// eslint-disable-next-line camelcase,no-underscore-dangle +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + // eslint-disable-next-line camelcase,no-underscore-dangle,no-use-before-define + __wbg_init.__wbindgen_wasm_module = module; + cachedUint32Memory0 = null; + + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + // eslint-disable-next-line no-param-reassign + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +// eslint-disable-next-line no-underscore-dangle,camelcase +async function __wbg_init(input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') { + // eslint-disable-next-line no-param-reassign + input = new URL('enigma_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + // eslint-disable-next-line no-param-reassign + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync }; +// eslint-disable-next-line camelcase +export default __wbg_init; diff --git a/tools/rum/enigma_bg.wasm b/tools/rum/enigma_bg.wasm new file mode 100644 index 0000000000000000000000000000000000000000..48a7a623954a79efac00e75406e57081943cfc87 GIT binary patch literal 14746 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" + ], "version": "0.1.0", - "scripts": { - "test": "node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=../../lcov.info --test-reporter=spec --test-reporter-destination=stdout --test-reporter=junit --test-reporter-destination=../../junit.xml" - }, - "type": "module" + "files": [ + "enigma_bg.wasm", + "enigma.js", + "enigma.d.ts" + ], + "module": "enigma.js", + "types": "enigma.d.ts", + "sideEffects": [ + "./snippets/*" + ] } \ No newline at end of file