tor-browser

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

commit a3a5cac5a06b9d69d45b9f4d888ab7e1b5667550
parent d88fce9a0c41a2f964864311edb4818d0a9b3cac
Author: James Teow <jteow@mozilla.com>
Date:   Tue, 28 Oct 2025 14:23:51 +0000

Bug 1986066 - Add a performance test for calculate_frecency - r=perftest-reviewers,mozperftest-reviewers,places-reviewers,sparky,Standard8

calculate_frecency determines frecency values for moz_places rows
in Places. We should add performance tests to understand the impact
of changes to the function, especially as we continue to evolve
the algorithm.

Differential Revision: https://phabricator.services.mozilla.com/D267276

Diffstat:
Mpython/mozperftest/perfdocs/config.yml | 5+++++
Mtaskcluster/kinds/perftest/linux.yml | 19+++++++++++++++++++
Mtaskcluster/kinds/perftest/macosx.yml | 19+++++++++++++++++++
Mtesting/perfdocs/generated/mozperftest.rst | 24++++++++++++++++++++++++
Atoolkit/components/places/tests/browser/performance/browser_calculate_frecency_speed.js | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atoolkit/components/places/tests/browser/performance/perftest.toml | 4++++
Mtoolkit/components/places/tests/moz.build | 1+
7 files changed, 256 insertions(+), 0 deletions(-)

diff --git a/python/mozperftest/perfdocs/config.yml b/python/mozperftest/perfdocs/config.yml @@ -95,3 +95,8 @@ suites: "browser_addManyNodes.js": "" "browser_reflowPseudoelements.js": "" "browser_removeManySpellingErrors.js": "" + + toolkit/components/places/tests/browser/performance: + description: "Performance tests for Toolkit: Places" + tests: + "Calculate Frecency Speed": "" diff --git a/taskcluster/kinds/perftest/linux.yml b/taskcluster/kinds/perftest/linux.yml @@ -780,3 +780,22 @@ perftest-accessibility: --flavor mochitest --output $MOZ_FETCHES_DIR/../artifacts accessible/tests/browser/performance/browser_removeManySpellingErrors.js + +perftest-places: + description: Run Places related performance tests + treeherder: + symbol: perftest(places) + tier: 2 + attributes: + batch: false + cron: false + run-on-projects: [mozilla-central] + run: + command: >- + mkdir -p $MOZ_FETCHES_DIR/../artifacts && + cd $MOZ_FETCHES_DIR && + python3 python/mozperftest/mozperftest/runner.py + --mochitest-binary ${MOZ_FETCHES_DIR}/firefox/firefox-bin + --flavor mochitest + --output $MOZ_FETCHES_DIR/../artifacts + toolkit/components/places/tests/browser/performance/browser_calculate_frecency_speed.js diff --git a/taskcluster/kinds/perftest/macosx.yml b/taskcluster/kinds/perftest/macosx.yml @@ -732,3 +732,22 @@ perftest-accessibility: --flavor mochitest --output $MOZ_FETCHES_DIR/../artifacts accessible/tests/browser/performance/browser_removeManySpellingErrors.js + +perftest-places: + description: Run Places related performance tests + treeherder: + symbol: perftest(places) + tier: 2 + attributes: + batch: false + cron: false + run-on-projects: [mozilla-central] + run: + command: >- + mkdir -p $MOZ_FETCHES_DIR/../artifacts && + cd $MOZ_FETCHES_DIR && + python3 python/mozperftest/mozperftest/runner.py + --mochitest-binary ${MOZ_FETCHES_DIR}/target.dmg + --flavor mochitest + --output $MOZ_FETCHES_DIR/../artifacts + toolkit/components/places/tests/browser/performance/browser_calculate_frecency_speed.js diff --git a/testing/perfdocs/generated/mozperftest.rst b/testing/perfdocs/generated/mozperftest.rst @@ -719,6 +719,30 @@ browser_ml_summarizer_perf.js **Template test for latency for Summarizer model** +toolkit/components/places/tests/browser/performance +--------------------------------------------------- +Performance tests for Toolkit: Places + +browser_calculate_frecency_speed.js +=================================== + +:owner: Places +:name: Calculate Frecency Speed +:Default options: + +:: + + --extra-args headless + --manifest perftest.toml + --manifest-flavor browser-chrome + --perfherder + --perfherder-metrics name:PlacesCalculateFrecencyHighFrequency,unit:ms,shouldAlert:False, name:PlacesCalculateFrecencyLowFrequency,unit:ms,shouldAlert:False, name:PlacesCalculateFrecencyChunked,unit:ms,shouldAlert:False + --try-platform linux, mac + --verbose + +**Audits the speed of running calculate_frecency.** + + toolkit/components/url-classifier/tests/performance --------------------------------------------------- Performance tests for the URL Classifier diff --git a/toolkit/components/places/tests/browser/performance/browser_calculate_frecency_speed.js b/toolkit/components/places/tests/browser/performance/browser_calculate_frecency_speed.js @@ -0,0 +1,184 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + AddonTestUtils: "resource://testing-common/AddonTestUtils.sys.mjs", + PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs", + PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", +}); + +const DEFAULT_CHUNK_SIZE = 50; + +// XXX: We can consolidate this once bug 1930955 lands +// eslint-disable-next-line no-unused-vars +const perfMetadata = { + owner: "Places", + name: "Calculate Frecency Speed", + description: "Audits the speed of running calculate_frecency.", + options: { + default: { + extra_args: ["headless"], + manifest: "perftest.toml", + manifest_flavor: "browser-chrome", + perfherder: true, + perfherder_metrics: [ + // Timing metrics. + { + name: "PlacesCalculateFrecencyHighFrequency", + unit: "ms", + shouldAlert: false, + }, + { + name: "PlacesCalculateFrecencyLowFrequency", + unit: "ms", + shouldAlert: false, + }, + { + name: "PlacesCalculateFrecencyChunked", + unit: "ms", + shouldAlert: false, + }, + ], + try_platform: ["linux", "mac"], + verbose: true, + }, + }, +}; + +function createTimer(metricName) { + let accumulatedTime = 0; + let iterations = 0; + let now = 0; + return { + start() { + now = ChromeUtils.now(); + }, + stop() { + accumulatedTime += ChromeUtils.now() - now; + iterations++; + }, + reportMetrics() { + const metrics = {}; + metrics[metricName] = accumulatedTime / iterations; + info(`perfMetrics | ${JSON.stringify(metrics)}`); + }, + }; +} + +add_task(async function measure_frecency_speed() { + let testData = [ + // High frequency, recent visits. + { + timerName: "PlacesCalculateFrecencyHighFrequency", + urls: [ + { + url: "https://www.mozilla.org/", + visits: [ + { + // 1 hour ago + date: new Date(Date.now() - 1000 * 60 * 60), + transition: PlacesUtils.history.TRANSITIONS.TYPED, + }, + { + // 1 day ago + date: new Date(Date.now() - 1000 * 60 * 60 * 24), + transition: PlacesUtils.history.TRANSITIONS.TYPED, + }, + { + // 7 days ago + date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7), + transition: PlacesUtils.history.TRANSITIONS.TYPED, + }, + { + // 14 days ago + date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 14), + transition: PlacesUtils.history.TRANSITIONS.TYPED, + }, + { + // 30 days ago + date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30), + transition: PlacesUtils.history.TRANSITIONS.TYPED, + }, + ], + }, + ], + }, + // Low frequency, old visit. + { + timerName: "PlacesCalculateFrecencyLowFrequency", + urls: [ + { + url: "https://old.mozilla.org/", + visits: [ + { + // 365 days ago + date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 365), + transition: PlacesUtils.history.TRANSITIONS.LINK, + }, + ], + }, + ], + }, + // Many different URLs. + { + timerName: "PlacesCalculateFrecencyChunked", + urls: [ + ...Array.from({ length: DEFAULT_CHUNK_SIZE }, (_, i) => ({ + url: `https://www.example${i}.com/`, + visits: [ + { + date: new Date(), + }, + ], + })), + ], + }, + ]; + + for (let item of testData) { + await PlacesUtils.bookmarks.eraseEverything(); + await PlacesUtils.history.clear(); + + let db = await PlacesUtils.promiseDBConnection(); + let initialIds = await db.executeCached(` + SELECT id FROM moz_places + ORDER BY id + `); + Assert.equal(initialIds.length, 0, "Places should be empty."); + + for (let urlData of item.urls) { + for (let visit of urlData.visits) { + await PlacesTestUtils.addVisits({ + uri: urlData.url, + visitDate: visit.date, + transition: visit.transition, + }); + } + } + let placeIds = await db.executeCached(` + SELECT id FROM moz_places + ORDER BY id + `); + Assert.equal( + placeIds.length, + item.urls.length, + "Places should match the number of URLs in the test." + ); + + let frecencyTimer = createTimer(item.timerName); + await PlacesUtils.withConnectionWrapper("Calculate Frecency", async db => { + frecencyTimer.start(); + await db.executeCached( + ` + UPDATE moz_places + SET frecency = CALCULATE_FRECENCY(id) + ` + ); + frecencyTimer.stop(); + }); + + frecencyTimer.reportMetrics(); + } +}); diff --git a/toolkit/components/places/tests/browser/performance/perftest.toml b/toolkit/components/places/tests/browser/performance/perftest.toml @@ -0,0 +1,4 @@ +[DEFAULT] + +["browser_calculate_frecency_speed.js"] +disabled = "Disabled as we want to run this only as perftest, not regular CI" diff --git a/toolkit/components/places/tests/moz.build b/toolkit/components/places/tests/moz.build @@ -25,6 +25,7 @@ XPCSHELL_TESTS_MANIFESTS += [ BROWSER_CHROME_MANIFESTS += [ "browser/browser.toml", + "browser/performance/perftest.toml", "browser/previews/browser.toml", ]