Optimize runtime of the find controller unit tests

The find controller tests consistently show up in the list of slowest
tests reported by Jasmine. Profiling shows that most of the time is
spent waiting for the find results to arrive, even though the find
command itself is quite fast.

It turns out that the slowdown occurs between receiving the `find` event
and actually triggering the search. The find controller has a hardcoded
delay of 250 milliseconds built in, which was introduced for viewer
performance many years ago because otherwise every keystroke would
trigger a search even though the user's query was not complete yet.

For the unit tests we don't need this delay because, contrary to the
viewer use case, we don't have to account for user interaction and
instead dispatch complete `find` events on the event bus ourselves.
However, since the unit tests were introduced well over a year after
the delay was introduced, due to an oversight it was never made
configurable so we could skip it for the unit tests.

This commit fixes the issue, which locally results in the runtime of
`npx gulp unittest --noChrome` dropping from 39.991 seconds before this
patch to 29.116 seconds afterwards, which is a 27% speedup.
This commit is contained in:
Tim van der Meij 2026-05-01 15:56:22 +02:00
parent 091b172a22
commit 038ca33f8e
No known key found for this signature in database
GPG Key ID: 8C3FD2925A5F2762
2 changed files with 19 additions and 4 deletions

View File

@ -72,10 +72,15 @@ async function initPdfFindController(
FindControllerClass.prototype.match = matcher;
}
// Note that in the unit tests we dispatch the `find` event with the complete
// query ourselves, so we can safely disable the delay option as there is no
// user interaction involved for typing the query (for which the delay option
// is intended), which provides a significant reduction in unit test runtime.
const pdfFindController = new FindControllerClass({
linkService,
eventBus,
updateMatchesCountOnProgress,
delay: 0,
});
pdfFindController.setDocument(pdfDocument); // Enable searching.

View File

@ -27,8 +27,6 @@ const FindState = {
PENDING: 3,
};
const FIND_TIMEOUT = 250; // ms
const CHARACTERS_TO_NORMALIZE = {
"\u2010": "-", // Hyphen
"\u2018": "'", // Left single quotation mark
@ -406,6 +404,10 @@ function getOriginalIndex(diffs, pos, len) {
* @typedef {Object} PDFFindControllerOptions
* @property {PDFLinkService} linkService - The navigation/linking service.
* @property {EventBus} eventBus - The application event bus.
* @property {number} [delay] - The number of milliseconds to delay execution of
* find commands. In the viewer each keystroke in the find bar triggers a
* `find` event, so this delay avoids triggering a search prematurely when the
* user is still typing the query. The default value is 250.
* @property {boolean} [updateMatchesCountOnProgress] - True if the matches
* count must be updated on progress or only when the last page is reached.
* The default value is `true`.
@ -419,6 +421,8 @@ class PDFFindController {
#updateMatchesCountOnProgress = true;
#delay = 0;
#visitedPagesCount = 0;
#copiedPageData = null;
@ -428,10 +432,16 @@ class PDFFindController {
/**
* @param {PDFFindControllerOptions} options
*/
constructor({ linkService, eventBus, updateMatchesCountOnProgress = true }) {
constructor({
linkService,
eventBus,
delay = 250,
updateMatchesCountOnProgress = true,
}) {
this._linkService = linkService;
this._eventBus = eventBus;
this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress;
this.#delay = delay;
/**
* Callback used to check if a `pageNumber` is currently visible.
@ -521,7 +531,7 @@ class PDFFindController {
this._findTimeout = setTimeout(() => {
this.#nextMatch();
this._findTimeout = null;
}, FIND_TIMEOUT);
}, this.#delay);
} else if (this._dirtyMatch) {
// Immediately trigger searching for non-'find' operations, when the
// current state needs to be reset and matches re-calculated.