From 7269c5355d257dd2ad2c53f15dc9c1cf6796aea5 Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 24 Mar 2022 02:04:04 +0600 Subject: [PATCH] significantly improve performance on large strings this replaces inefficient pattern of `MIN(TEXTW(..), n)` with drw_fontset_getwidth_clamp() instead, which is far more efficient when we only want up to a certain width. dumping a decently sized (unicode) emoji file into dmenu, I see the startup time drop significantly with this patch. before -> after 360ms -> 160ms this should also noticeably improve input latency (responsiveness) given that calcoffsets() and drawmenu() are pretty hot functions. --- dmenu.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/dmenu.c b/dmenu.c index eca67ac..cde394b 100644 --- a/dmenu.c +++ b/dmenu.c @@ -58,6 +58,13 @@ static Clr *scheme[SchemeLast]; static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; static char *(*fstrstr)(const char *, const char *) = strstr; +static unsigned int +textw_clamp(const char *str, unsigned int n) +{ + unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad; + return MIN(w, n); +} + static void appenditem(struct item *item, struct item **list, struct item **last) { @@ -82,10 +89,10 @@ calcoffsets(void) n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); /* calculate which items will begin the next page and previous page */ for (i = 0, next = curr; next; next = next->right) - if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n) + if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) break; for (i = 0, prev = curr; prev && prev->left; prev = prev->left) - if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) + if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n) break; } @@ -172,7 +179,7 @@ drawmenu(void) } x += w; for (item = curr; item != next; item = item->right) - x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">"))); + x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">"))); if (next) { w = TEXTW(">"); drw_setscheme(drw, scheme[SchemeNorm]);