From 4cd093aa57aa92f014c2bc2a4a0f92ddc301f9f8 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 24 Jul 2024 16:13:54 +0200 Subject: [PATCH] base async implementation --- resources/benchmark-runner.mjs | 111 ++++++++++++++++++++++++++------- resources/tests.mjs | 24 ++++++- 2 files changed, 112 insertions(+), 23 deletions(-) diff --git a/resources/benchmark-runner.mjs b/resources/benchmark-runner.mjs index 47084c8a4..4927bb59b 100644 --- a/resources/benchmark-runner.mjs +++ b/resources/benchmark-runner.mjs @@ -7,6 +7,13 @@ export class BenchmarkTestStep { constructor(testName, testFunction) { this.name = testName; this.run = testFunction; + this.isAsync = false; + } +} +export class AsyncBenchmarkTestStep extends BenchmarkTestStep { + constructor(testName, testFunction) { + super(testName, testFunction); + this.isAsync = true; } } @@ -287,7 +294,24 @@ class TimerTestInvoker extends TestInvoker { } } -class RAFTestInvoker extends TestInvoker { +class AsyncTimerTestInvoker extends TestInvoker { + start() { + return new Promise((resolve) => { + setTimeout(async () => { + await this._syncCallback(); + setTimeout(() => { + this._asyncCallback(); + requestAnimationFrame(async () => { + await this._reportCallback(); + resolve(); + }); + }, 0); + }, params.waitBeforeSync); + }); + } +} + +class BaseRAFTestInvoker extends TestInvoker { start() { return new Promise((resolve) => { if (params.waitBeforeSync) @@ -296,7 +320,9 @@ class RAFTestInvoker extends TestInvoker { this._scheduleCallbacks(resolve); }); } +} +class RAFTestInvoker extends BaseRAFTestInvoker { _scheduleCallbacks(resolve) { requestAnimationFrame(() => this._syncCallback()); requestAnimationFrame(() => { @@ -311,6 +337,23 @@ class RAFTestInvoker extends TestInvoker { } } +class AsyncRAFTestInvoker extends BaseRAFTestInvoker { + _scheduleCallbacks(resolve) { + requestAnimationFrame(async () => { + await this._syncCallback(); + requestAnimationFrame(() => { + setTimeout(() => { + this._asyncCallback(); + setTimeout(async () => { + await this._reportCallback(); + resolve(); + }, 0); + }, 0); + }); + }); + } +} + // https://stackoverflow.com/a/47593316 function seededHashRandomNumberGenerator(a) { return function () { @@ -466,26 +509,53 @@ export class BenchmarkRunner { let syncTime; let asyncStartTime; let asyncTime; - const runSync = () => { - if (params.warmupBeforeSync) { - performance.mark("warmup-start"); - const startTime = performance.now(); - // Infinite loop for the specified ms. - while (performance.now() - startTime < params.warmupBeforeSync) - continue; - performance.mark("warmup-end"); + let runSync; + let invokerClass; + if (!test.isAsync) { + invokerClass = params.measurementMethod === "raf" ? RAFTestInvoker : TimerTestInvoker; + runSync = () => { + if (params.warmupBeforeSync) { + performance.mark("warmup-start"); + const startTime = performance.now(); + // Infinite loop for the specified ms. + while (performance.now() - startTime < params.warmupBeforeSync) + continue; + performance.mark("warmup-end"); + } + performance.mark(startLabel); + const syncStartTime = performance.now(); + test.run(this._page); + const syncEndTime = performance.now(); + performance.mark(syncEndLabel); + + syncTime = syncEndTime - syncStartTime; + + performance.mark(asyncStartLabel); + asyncStartTime = performance.now(); } - performance.mark(startLabel); - const syncStartTime = performance.now(); - test.run(this._page); - const syncEndTime = performance.now(); - performance.mark(syncEndLabel); - - syncTime = syncEndTime - syncStartTime; - - performance.mark(asyncStartLabel); - asyncStartTime = performance.now(); - }; + } else { + invokerClass = params.measurementMethod === "raf" ? AsyncRAFTestInvoker : AsyncTimerTestInvoker; + runSync = async () => { + if (params.warmupBeforeSync) { + performance.mark("warmup-start"); + const startTime = performance.now(); + // Infinite loop for the specified ms. + while (performance.now() - startTime < params.warmupBeforeSync) + continue; + performance.mark("warmup-end"); + } + performance.mark(startLabel); + const syncStartTime = performance.now(); + await test.run(this._page); + const syncEndTime = performance.now(); + performance.mark(syncEndLabel); + + syncTime = syncEndTime - syncStartTime; + + performance.mark(asyncStartLabel); + asyncStartTime = performance.now(); + }; + } const measureAsync = () => { // Some browsers don't immediately update the layout for paint. // Force the layout here to ensure we're measuring the layout time. @@ -500,7 +570,6 @@ export class BenchmarkRunner { performance.measure(`${suite.name}.${test.name}-async`, asyncStartLabel, asyncEndLabel); }; const report = () => this._recordTestResults(suite, test, syncTime, asyncTime); - const invokerClass = params.measurementMethod === "raf" ? RAFTestInvoker : TimerTestInvoker; const invoker = new invokerClass(runSync, measureAsync, report); return invoker.start(); diff --git a/resources/tests.mjs b/resources/tests.mjs index 625ae4f89..1d9b6842f 100644 --- a/resources/tests.mjs +++ b/resources/tests.mjs @@ -1,4 +1,4 @@ -import { BenchmarkTestStep } from "./benchmark-runner.mjs"; +import { BenchmarkTestStep, AsyncBenchmarkTestStep } from "./benchmark-runner.mjs"; import { todos } from "./translations.mjs"; const numberOfItemsToAdd = 100; @@ -953,7 +953,27 @@ Suites.push({ page.querySelector("#add-scatter-chart-button").click(); }), ], -}); +}) + +Suites.push({ + name: "Charts-chartjs-Async", + url: "charts/dist/chartjs.html", + tags: ["chart"], + async prepare(page) {}, + tests: [ + new AsyncBenchmarkTestStep("Draw scatter", (page) => { + page.querySelector("#prepare").click(); + page.querySelector("#add-scatter-chart-button").click(); + }), + new AsyncBenchmarkTestStep("Show tooltip", (page) => { + page.querySelector("#open-tooltip").click(); + }), + new AsyncBenchmarkTestStep("Draw opaque scatter", (page) => { + page.querySelector("#opaque-color").click(); + page.querySelector("#add-scatter-chart-button").click(); + }), + ], +});; Suites.push({ name: "React-Stockcharts-SVG",