]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
ui: throttle curses redraws during packet bursts 569/head
authorDarafei Praliaskouski <me@komzpa.net>
Fri, 1 May 2026 13:22:45 +0000 (17:22 +0400)
committerDarafei Praliaskouski <me@komzpa.net>
Fri, 1 May 2026 13:22:45 +0000 (17:22 +0400)
ui/select.c

index b44fc5312ac7f590f4eae521576474ea9747a892..a854c22ab6d0b8f3c50432b93de5ce216b26caef 100644 (file)
 #include "display.h"
 #include "select.h"
 
+#define MIN_DISPLAY_REDRAW_USEC 100000
+
+static int timeval_after_or_equal(
+    const struct timeval *a,
+    const struct timeval *b)
+{
+    if (a->tv_sec > b->tv_sec)
+        return 1;
+    if (a->tv_sec < b->tv_sec)
+        return 0;
+
+    return a->tv_usec >= b->tv_usec;
+}
+
+static void timeval_add_usec(
+    struct timeval *timeval,
+    int usec)
+{
+    timeval->tv_usec += usec;
+    timeval->tv_sec += timeval->tv_usec / 1000000;
+    timeval->tv_usec %= 1000000;
+}
+
+static void timeval_subtract(
+    struct timeval *result,
+    const struct timeval *end,
+    const struct timeval *start)
+{
+    result->tv_usec = end->tv_usec - start->tv_usec;
+    result->tv_sec = end->tv_sec - start->tv_sec;
+
+    if (result->tv_usec < 0) {
+        --result->tv_sec;
+        result->tv_usec += 1000000;
+    }
+
+    if (result->tv_sec < 0) {
+        result->tv_sec = 0;
+        result->tv_usec = 0;
+    }
+}
+
+static void timeval_min(
+    struct timeval *timeval,
+    const struct timeval *limit)
+{
+    if (timeval_after_or_equal(timeval, limit))
+        *timeval = *limit;
+}
+
 void select_loop(
     struct mtr_ctl *ctl)
 {
@@ -56,6 +106,7 @@ void select_loop(
     int paused = 0;
     struct timeval lasttime, thistime, selecttime;
     struct timeval startgrace;
+    struct timeval nextredraw;
     int dt;
     int rv;
     int graceperiod = 0;
@@ -65,6 +116,7 @@ void select_loop(
     memset(&startgrace, 0, sizeof(startgrace));
 
     gettimeofday(&lasttime, NULL);
+    nextredraw = lasttime;
 
     while (1) {
         dt = calc_deltatime(ctl->WaitTime);
@@ -120,11 +172,15 @@ void select_loop(
                             &selecttime);
 
             } else {
-                if (ctl->Interactive)
-                    display_redraw(ctl);
-
                 gettimeofday(&thistime, NULL);
 
+                if (ctl->Interactive
+                    && timeval_after_or_equal(&thistime, &nextredraw)) {
+                    display_redraw(ctl);
+                    nextredraw = thistime;
+                    timeval_add_usec(&nextredraw, MIN_DISPLAY_REDRAW_USEC);
+                }
+
                 if (thistime.tv_sec > lasttime.tv_sec + intervaltime.tv_sec
                     || (thistime.tv_sec ==
                         lasttime.tv_sec + intervaltime.tv_sec
@@ -178,6 +234,17 @@ void select_loop(
                     }
                 }
 
+                if (ctl->Interactive) {
+                    struct timeval redrawtime;
+
+                    /*
+                     * Packet and resolver events must still be handled
+                     * immediately; only terminal repainting is capped.
+                     */
+                    timeval_subtract(&redrawtime, &nextredraw, &thistime);
+                    timeval_min(&selecttime, &redrawtime);
+                }
+
                 rv = select(maxfd, (void *) &readfd, NULL, NULL,
                             &selecttime);
             }