performance: Use startsWith in many places.

Using startsWith is faster than indexOf, especially for long strings
and short prefixes.  It's also a lot more readable.  The only reason
we weren't using it was when a lot of the code was originally written,
it wasn't available.
This commit is contained in:
Steve Howell
2020-01-28 14:26:02 +00:00
committed by Tim Abbott
parent d3e961e179
commit d0453dc8f4
8 changed files with 23 additions and 17 deletions

View File

@@ -71,13 +71,13 @@ exports.phrase_match = function (query, phrase) {
query = query.toLowerCase(); query = query.toLowerCase();
phrase = phrase.toLowerCase(); phrase = phrase.toLowerCase();
if (phrase.indexOf(query) === 0) { if (phrase.startsWith(query)) {
return true; return true;
} }
const parts = phrase.split(' '); const parts = phrase.split(' ');
for (i = 0; i < parts.length; i += 1) { for (i = 0; i < parts.length; i += 1) {
if (parts[i].indexOf(query) === 0) { if (parts[i].startsWith(query)) {
return true; return true;
} }
} }

View File

@@ -958,7 +958,7 @@ exports.initialize = function () {
// The matcher for "stream" is strictly prefix-based, // The matcher for "stream" is strictly prefix-based,
// because we want to avoid mixing up streams. // because we want to avoid mixing up streams.
const q = this.query.trim().toLowerCase(); const q = this.query.trim().toLowerCase();
return item.toLowerCase().indexOf(q) === 0; return item.toLowerCase().startsWith(q);
}, },
}); });

View File

@@ -170,7 +170,7 @@ exports.add_topic_links = function (message) {
}; };
exports.is_status_message = function (raw_content) { exports.is_status_message = function (raw_content) {
return raw_content.indexOf('/me ') === 0; return raw_content.startsWith('/me ');
}; };
function make_emoji_span(codepoint, title, alt_text) { function make_emoji_span(codepoint, title, alt_text) {
@@ -251,7 +251,7 @@ function handleTex(tex, fullmatch) {
try { try {
return katex.renderToString(tex); return katex.renderToString(tex);
} catch (ex) { } catch (ex) {
if (ex.message.indexOf('KaTeX parse error') === 0) { // TeX syntax error if (ex.message.startsWith('KaTeX parse error')) { // TeX syntax error
return '<span class="tex-error">' + escape(fullmatch) + '</span>'; return '<span class="tex-error">' + escape(fullmatch) + '</span>';
} }
blueslip.error(ex); blueslip.error(ex);

View File

@@ -824,7 +824,7 @@ exports.build_termlet_matcher = function (termlet) {
const names = full_name.toLowerCase().split(' '); const names = full_name.toLowerCase().split(' ');
return _.any(names, function (name) { return _.any(names, function (name) {
if (name.indexOf(termlet) === 0) { if (name.startsWith(termlet)) {
return true; return true;
} }
}); });
@@ -840,7 +840,7 @@ exports.build_person_matcher = function (query) {
return function (user) { return function (user) {
const email = user.email.toLowerCase(); const email = user.email.toLowerCase();
if (email.indexOf(query) === 0) { if (email.startsWith(query)) {
return true; return true;
} }

View File

@@ -415,10 +415,11 @@ function get_special_filter_suggestions(last, operators, suggestions) {
// returns the substring after the ":" symbol. // returns the substring after the ":" symbol.
const suggestion_operand = s.search_string.substring(s.search_string.indexOf(":") + 1); const suggestion_operand = s.search_string.substring(s.search_string.indexOf(":") + 1);
// e.g for `att` search query, `has:attachment` should be suggested. // e.g for `att` search query, `has:attachment` should be suggested.
const show_operator_suggestions = last.operator === 'search' && suggestion_operand.toLowerCase().indexOf(last_string) === 0; const show_operator_suggestions = last.operator === 'search' &&
return s.search_string.toLowerCase().indexOf(last_string) === 0 || suggestion_operand.toLowerCase().startsWith(last_string);
return s.search_string.toLowerCase().startsWith(last_string) ||
show_operator_suggestions || show_operator_suggestions ||
s.description.toLowerCase().indexOf(last_string) === 0; s.description.toLowerCase().startsWith(last_string);
}); });
// Only show home if there's an empty bar // Only show home if there's an empty bar
@@ -541,15 +542,20 @@ function get_sent_by_me_suggestions(last, operators) {
return []; return [];
} }
if (last.operator === '' || sender_query.indexOf(last_string) === 0 || if (last.operator === '' ||
sender_me_query.indexOf(last_string) === 0 || last_string === sent_string) { sender_query.startsWith(last_string) ||
sender_me_query.startsWith(last_string) ||
last_string === sent_string
) {
return [ return [
{ {
search_string: sender_query, search_string: sender_query,
description: description, description: description,
}, },
]; ];
} else if (from_query.indexOf(last_string) === 0 || from_me_query.indexOf(last_string) === 0) { } else if (from_query.startsWith(last_string) ||
from_me_query.startsWith(last_string)
) {
return [ return [
{ {
search_string: from_query, search_string: from_query,
@@ -567,7 +573,7 @@ function get_operator_suggestions(last) {
let last_operand = last.operand; let last_operand = last.operand;
let negated = false; let negated = false;
if (last_operand.indexOf("-") === 0) { if (last_operand.startsWith("-")) {
negated = true; negated = true;
last_operand = last_operand.slice(1); last_operand = last_operand.slice(1);
} }

View File

@@ -25,7 +25,7 @@ function filter_streams_by_search(streams, search_term) {
const cands = lower_stream_name.split(" "); const cands = lower_stream_name.split(" ");
cands.push(lower_stream_name); cands.push(lower_stream_name);
return _.any(cands, function (name) { return _.any(cands, function (name) {
return name.indexOf(search_term) === 0; return name.startsWith(search_term);
}); });
}); });
}); });

View File

@@ -1,5 +1,5 @@
function make_upload_absolute(uri) { function make_upload_absolute(uri) {
if (uri.indexOf(compose.uploads_path) === 0) { if (uri.startsWith(compose.uploads_path)) {
// Rewrite the URI to a usable link // Rewrite the URI to a usable link
return compose.uploads_domain + uri; return compose.uploads_domain + uri;
} }

View File

@@ -30,7 +30,7 @@ function query_matches_string(query, source_str, split_char) {
if (sources[i] === undefined) { if (sources[i] === undefined) {
return false; return false;
} }
return sources[i].indexOf(queries[i]) === 0; return sources[i].startsWith(queries[i]);
} }
// For a single token, the match can be anywhere in the string. // For a single token, the match can be anywhere in the string.