Skip to content

Micro-optimize search#482

Open
trotzig wants to merge 7 commits into
javve:masterfrom
trotzig:micro-optimize-search
Open

Micro-optimize search#482
trotzig wants to merge 7 commits into
javve:masterfrom
trotzig:micro-optimize-search

Conversation

@trotzig

@trotzig trotzig commented Jan 13, 2017

Copy link
Copy Markdown

This PR started out with me exploring whether to move some of the functions used when searching over to a web worker, but ended up just making a few minor improvements to the matching behavior. I call it "micro-optimize" because the DOM manipulation is still the most expensive part of list.js searching.

Henric Trotzig added 5 commits January 13, 2017 11:28
With newer versions of npm, the node_modules folder is flattened.
Instead of reaching into grunt-mocha/node_modules to find mocha.css and
mocha.js, we need to look directly in the mocha folder.
By doing this, we make `setSearchString` twice as fast. It's already
pretty fast, but this won't hurt.
By memoizing a RegExp instead of matching against a string, the total
time to search goes down with about 30-60%.

This is the total search times for strings "l" and "le" on a list of
1000 items (most items named "Leia <n>", where <n> is a incremented
number).

Without RegExp memoization:

  first run: 3.2ms
  second run: 1.63ms

With RegExp memoization:

  first run: 2.16ms
  second run: 0.7ms
Instead of converting to lower-case before we match a string, we can
tell the regexp to do this for us. This makes searching a little bit
faster, roughly 25% in my local testing.
Since we don't care about where in the string the match was, we can use
RegExp.test directly (which returns a boolean). This might make
searching a little faster, although I didn't see any significant signs
of that in my local testing.
Comment thread src/search.js
list.searched = true;
if (customSearch) {
customSearch(searchString, columns);
customSearch(searchPattern, columns);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a breaking change, depending on how people use the customSearch option.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

searchPattern.source could help.

Henric Trotzig added 2 commits January 14, 2017 22:09
By using a range, we can improve performance of templater.clear() by
roughly 25% (tested in Chrome). I decided to make this perf enhancement
opt-in to browsers supporting the `document.createRange` method. It's
not supported in IE<9, but most modern browsers should have it.

On a list with 1000 items, this change took down the time it takes for
templater.clear() from roughly 40ms to <30ms. In total, the whole
search execution takes about 160ms, so this shaves off ~6% of execution
time.
By adding DOM nodes one by one, we're causing multiple reflows in the
browser. This can have bad effects on performane when lists are longs.
By adding DOM nodes to a fragment we can limit the number of reflows to
one. This cuts execution time for list.update() in half (40ms to 20ms)
on a list with 1000 items.

While I was in the code, I noticed a misspelled comment that I fixed.
Comment thread src/search.js Outdated
prepare.setColumns();

if (searchString === "" ) {
if (!searchPattern ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

searchPattern will never be null:

console.log(new RegExp());
// output: /(?:)/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants