I have a really weird effect in the web application I wrote. The number of current search results has a huge impact on the speed of the next search, even if the search does not use the list of results in any way.
I'm not sure how much code I should post here to demonstrate what the application does, but the whole application is online http://connective-lex.info . (To see the effect, select all the lexicons, then change the search options, for example, mark one or nothing.)
This is a query function. The first line marked !!! , deletes the previous list of results, which leads to a really quick search. If this line is commented out, the search starts a little faster, but then very slowly if many items are in the previous list of results.
The result list is this.results and is not used in search code. It is also not used in the ResultsFilter class, which does the actual filtering, which I omit for brevity, but gladly send more code if you need more.
// File: c24-components.js // Class: ResultsComponent ExecuteQuery() { setTimeout(() => this.SetResults([]), 0); // !!! let tempResults = []; let lexIds = Object.keys(gSelectorComponent.lex); let totalSize = lexIds.map(lexId => gSelectorComponent.lex[lexId].entry.length). reduce((acc, val) => acc + val, 0); let resultsFilter = new ResultsFilter(totalSize); let processAtOnce = 20; this.activeSearches.forEach(timeoutId => clearTimeout(timeoutId)); this.activeSearches.length = 0; /* Subfunction which emulates asynchronous processing in the (single-threaded) JS environment by processing a slice of entries and then enqueuing the next slice to be processed so that the browser has time to process user events and render the GUI between slices. */ let processingFunction = (lexIdIndex, entryIndex) => { if (lexIdIndex >= lexIds.length) { this.activeSearches.push(setTimeout(() => this.SetResults(tempResults), 0)); return; } let entries = undefined; try { entries = gSelectorComponent.lex[lexIds[lexIdIndex]].entry; } catch (e) { // This happens when a lexicon is deselected while a search is running. // Abort search. return; } for (let i = 0; i < processAtOnce; ++i, ++entryIndex) { if (entryIndex >= entries.length) { this.activeSearches.push(setTimeout(processingFunction, 0, ++lexIdIndex, 0)); return; } if (resultsFilter.TestEntry(entries[entryIndex])) { tempResults.push(entries[entryIndex]); } } this.activeSearches.push(setTimeout(processingFunction, 0, lexIdIndex, entryIndex)); }; this.activeSearches.push(setTimeout(processingFunction, 0, 0, 0)); }
Update. If I interpret Chrome's performance tools correctly, this is a reflow problem caused by updating the progress bar. With each update, JS spends a lot of time on the Renderer update the Layer Tree, which seems to be the only difference that takes longer if the previous results are displayed. I wonder how I can get rid of this effect, but still demonstrate progress.