performance: Speed up search bar highlighting.

When we're highlighting all the people that show
up in a search from the search bar, we need
to fairly expensively build a regex from the
query:

    query = query.toLowerCase();
    query = query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
    const regex = new RegExp('(^' + query + ')', 'ig');

Even though the final regex is presumably cached, we
still needed to do that `query.replace` for every person.
Even for relatively small numbers of persons, this would
show up in profiles as expensive.

Now we just build the query once by using a pattern
where you call a function outside the loop to build
an inner function that's used in the loop that closes
on the `query` above.  The diff probably shows this
better than I explained it here.
This commit is contained in:
Steve Howell
2019-12-24 14:31:52 +00:00
committed by Tim Abbott
parent 6a9eaebff2
commit abdd4b54f4
2 changed files with 26 additions and 17 deletions

View File

@@ -2,12 +2,15 @@ function stream_matches_query(stream_name, q) {
return common.phrase_match(q, stream_name); return common.phrase_match(q, stream_name);
} }
function highlight_person(query, person) { function make_person_highlighter(query) {
const hilite = typeahead_helper.highlight_query_in_phrase; const hilite = typeahead_helper.make_query_highlighter(query);
return function (person) {
if (settings_org.show_email()) { if (settings_org.show_email()) {
return hilite(query, person.full_name) + " <" + hilite(query, person.email) + ">"; return hilite(person.full_name) + " <" + hilite(person.email) + ">";
} }
return hilite(query, person.full_name); return hilite(person.full_name);
};
} }
function match_criteria(operators, criteria) { function match_criteria(operators, criteria) {
@@ -148,13 +151,15 @@ function get_group_suggestions(all_persons, last, operators) {
const prefix = Filter.operator_to_prefix('pm-with', negated); const prefix = Filter.operator_to_prefix('pm-with', negated);
const highlight_person = make_person_highlighter(last_part);
const suggestions = _.map(persons, function (person) { const suggestions = _.map(persons, function (person) {
const term = { const term = {
operator: 'pm-with', operator: 'pm-with',
operand: all_but_last_part + ',' + person.email, operand: all_but_last_part + ',' + person.email,
negated: negated, negated: negated,
}; };
const name = highlight_person(last_part, person); const name = highlight_person(person);
const description = prefix + ' ' + Handlebars.Utils.escapeExpression(all_but_last_part) + ',' + name; const description = prefix + ' ' + Handlebars.Utils.escapeExpression(all_but_last_part) + ',' + name;
let terms = [term]; let terms = [term];
if (negated) { if (negated) {
@@ -202,8 +207,10 @@ function get_person_suggestions(all_persons, last, operators, autocomplete_opera
const prefix = Filter.operator_to_prefix(autocomplete_operator, last.negated); const prefix = Filter.operator_to_prefix(autocomplete_operator, last.negated);
const highlight_person = make_person_highlighter(query);
const objs = _.map(persons, function (person) { const objs = _.map(persons, function (person) {
const name = highlight_person(query, person); const name = highlight_person(person);
const description = prefix + ' ' + name; const description = prefix + ' ' + name;
const terms = [{ const terms = [{
operator: autocomplete_operator, operator: autocomplete_operator,

View File

@@ -51,12 +51,13 @@ exports.highlight_with_escaping_and_regex = function (regex, item) {
return result; return result;
}; };
exports.highlight_query_in_phrase = function (query, phrase) { exports.make_query_highlighter = function (query) {
let i; let i;
query = query.toLowerCase(); query = query.toLowerCase();
query = query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); query = query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
const regex = new RegExp('(^' + query + ')', 'ig'); const regex = new RegExp('(^' + query + ')', 'ig');
return function (phrase) {
let result = ""; let result = "";
const parts = phrase.split(' '); const parts = phrase.split(' ');
for (i = 0; i < parts.length; i += 1) { for (i = 0; i < parts.length; i += 1) {
@@ -67,6 +68,7 @@ exports.highlight_query_in_phrase = function (query, phrase) {
} }
return result; return result;
}; };
};
exports.render_typeahead_item = function (args) { exports.render_typeahead_item = function (args) {
args.has_image = args.img_src !== undefined; args.has_image = args.img_src !== undefined;