[hackers] [dwm] manage: propertynotify: Reduce cost of unused size hints || Chris Down

From: <git_AT_suckless.org>
Date: Sat, 16 Apr 2022 16:38:56 +0200 (CEST)

commit 8806b6e2379372900e3d9e0bf6604bc7f727350b
Author: Chris Down <chris_AT_chrisdown.name>
AuthorDate: Thu Mar 17 15:56:13 2022 +0000
Commit: Hiltjo Posthuma <hiltjo_AT_codemadness.org>
CommitDate: Sat Apr 16 16:37:46 2022 +0200

    manage: propertynotify: Reduce cost of unused size hints
    
    This patch defers all size hint calculations until they are actually
    needed, drastically reducing the number of calls to updatesizehints(),
    which can be expensive when called repeatedly (as it currently is during
    resizes).
    
    In my unscientific testing this reduces calls to updatesizehints() by
    over 90% during a typical work session. There are no functional changes
    for users other than an increase in responsiveness after resizes and
    a reduction in CPU time.
    
    In slower environments or X servers, this patch also offers an
    improvement in responsiveness that is often tangible after resizing a
    client that changes hints during resizes.
    
    There are two main motivations to defer this work to the time of hint
    application:
    
    1. Some clients, especially terminals using incremental size hints,
       resend XA_WM_NORMAL_HINTS events on resize to avoid fighting with the
       WM or mouse resizing. For example, some terminals like urxvt clear
       PBaseSize and PResizeInc during XResizeWindow and restore them
       afterwards.
    
       For this reason, after the resize is concluded, we typically receive
       a backlogged XA_WM_NORMAL_HINTS message for each update period with
       movement, which is useless. In some cases one may get hundreds or
       thousands of XA_WM_NORMAL_HINTS messages on large resizes, and
       currently all of these result in a separate updatesizehints() call,
       of which all but the final one are immediately outdated.
    
       (We can't just blindly discard these messages during resizes like we
       do for EnterNotify, because some of them might actually be for other
       windows, and may not be XA_WM_NORMAL_HINTS events.)
    
    2. For users which use resizehints=0 most of these updates are unused
       anyway -- in the normal case where the client is not floating these
       values won't be used, so there's no need to calculate them up front.
    
    A synthetic test using the mouse to resize a floating terminal window
    from roughly 256x256 to 1024x1024 and back again shows that the number
    of calls to updatesizehints() goes from over 500 before this patch (one
    for each update interval with movement) to 2 after this patch (one for
    each hint application), with no change in user visible behaviour.
    
    This also reduces the delay before dwm is ready to process new events
    again after a large resize on such a client, as it avoids the thundering
    herd of updatesizehints() calls when hundreds of backlogged
    XA_WM_NORMAL_HINTS messages appear at once after a resize is finished.

diff --git a/dwm.c b/dwm.c
index 5f16260..d8075ad 100644
--- a/dwm.c
+++ b/dwm.c
_AT_@ -89,7 +89,7 @@ struct Client {
         float mina, maxa;
         int x, y, w, h;
         int oldx, oldy, oldw, oldh;
- int basew, baseh, incw, inch, maxw, maxh, minw, minh;
+ int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
         int bw, oldbw;
         unsigned int tags;
         int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
_AT_@ -345,6 +345,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
         if (*w < bh)
                 *w = bh;
         if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
+ if (!c->hintsvalid)
+ updatesizehints(c);
                 /* see last two sentences in ICCCM 4.1.2.3 */
                 baseismin = c->basew == c->minw && c->baseh == c->minh;
                 if (!baseismin) { /* temporarily remove base dimensions */
_AT_@ -1059,7 +1061,6 @@ manage(Window w, XWindowAttributes *wa)
         XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
         configure(c); /* propagates border_width, if size doesn't change */
         updatewindowtype(c);
- updatesizehints(c);
         updatewmhints(c);
         XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
         grabbuttons(c, 0);
_AT_@ -1233,7 +1234,7 @@ propertynotify(XEvent *e)
                                 arrange(c->mon);
                         break;
                 case XA_WM_NORMAL_HINTS:
- updatesizehints(c);
+ c->hintsvalid = 0;
                         break;
                 case XA_WM_HINTS:
                         updatewmhints(c);
_AT_@ -1989,6 +1990,7 @@ updatesizehints(Client *c)
         } else
                 c->maxa = c->mina = 0.0;
         c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
+ c->hintsvalid = 1;
 }
 
 void
Received on Sat Apr 16 2022 - 16:38:56 CEST

This archive was generated by hypermail 2.3.0 : Sat Apr 16 2022 - 16:48:34 CEST