From: Kevin McCarthy Date: Mon, 19 Nov 2018 03:13:20 +0000 (-0800) Subject: Switch color chunk matching to use bsearch X-Git-Tag: 2019-10-25~485^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43cce31a523ad2e379201469144134e4a84276ee;p=neomutt Switch color chunk matching to use bsearch Emails with extremely long lines, combined with a large number of color matches, can cause a performance hit so severe that mutt appears to have hung. Switching out to using a binary search speeds things up noticably. The for loops being replaced were a bit strange. resolve_types() ensures there are no overlaps, and that they are ordered. A match is defined by (first <= cnt < last). I can't see any reason for the strange comparison of (cnt > last) follow by (cnt != last). Perhaps at one time it made sense. --- diff --git a/pager.c b/pager.c index f24f6874a..6ac430ca7 100644 --- a/pager.c +++ b/pager.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -246,6 +247,26 @@ static int check_sig(const char *s, struct Line *info, int n) return 0; } +/** + * comp_syntax_t - Search for a Syntax using bsearch + * @param m1 Search key + * @param m2 Array member + * @retval -1 m1 precedes m2 + * @retval 0 m1 matches m2 + * @retval 1 m2 precedes m1 + */ +static int comp_syntax_t(const void *m1, const void *m2) +{ + const int *cnt = (const int *) m1; + const struct Syntax *stx = (const struct Syntax *) m2; + + if (*cnt < stx->first) + return -1; + if (*cnt >= stx->last) + return 1; + return 0; +} + /** * resolve_color - Set the colour for a line of text * @param line_info Line info array @@ -263,6 +284,7 @@ static void resolve_color(struct Line *line_info, int n, int cnt, int flags, static int last_color; /* last color set */ bool search = false; int m; + struct Syntax *matching_chunk = NULL; if (!cnt) last_color = -1; /* force attrset() */ @@ -308,39 +330,26 @@ static void resolve_color(struct Line *line_info, int n, int cnt, int flags, } color = def_color; - if (flags & MUTT_SHOWCOLOR) + if ((flags & MUTT_SHOWCOLOR) && line_info[m].chunks) { - for (int i = 0; i < line_info[m].chunks; i++) + matching_chunk = bsearch(&cnt, line_info[m].syntax, line_info[m].chunks, + sizeof(struct Syntax), comp_syntax_t); + if (matching_chunk && (cnt >= matching_chunk->first) && + (cnt < matching_chunk->last)) { - /* we assume the chunks are sorted */ - if (cnt > (line_info[m].syntax)[i].last) - continue; - if (cnt < (line_info[m].syntax)[i].first) - break; - if (cnt != (line_info[m].syntax)[i].last) - { - color = (line_info[m].syntax)[i].color; - break; - } - /* don't break here, as cnt might be - * in the next chunk as well */ + color = matching_chunk->color; } } - if (flags & MUTT_SEARCH) + if ((flags & MUTT_SEARCH) && line_info[m].search_cnt) { - for (int i = 0; i < line_info[m].search_cnt; i++) + matching_chunk = bsearch(&cnt, line_info[m].search, line_info[m].search_cnt, + sizeof(struct Syntax), comp_syntax_t); + if (matching_chunk && (cnt >= matching_chunk->first) && + (cnt < matching_chunk->last)) { - if (cnt > (line_info[m].search)[i].last) - continue; - if (cnt < (line_info[m].search)[i].first) - break; - if (cnt != (line_info[m].search)[i].last) - { - color = ColorDefs[MT_COLOR_SEARCH]; - search = true; - break; - } + color = ColorDefs[MT_COLOR_SEARCH]; + search = 1; } }