Mercurial > ~mikael > mcabber > hg
diff mcabber/mcabber/main.c @ 2281:1bb9002801e5
Limit the number of roster computations/redraws per second
This reduces CPU time and greatly improve performance with very large
rosters (e.g. >1000 items).
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 25 Sep 2016 15:07:24 +0200 |
parents | f5402d705f67 |
children | ece02eb9c81d |
line wrap: on
line diff
--- a/mcabber/mcabber/main.c Sat Sep 24 12:31:13 2016 +0200 +++ b/mcabber/mcabber/main.c Sun Sep 25 15:07:24 2016 +0200 @@ -28,6 +28,7 @@ #include <glib.h> #include <config.h> #include <poll.h> +#include <time.h> #include <errno.h> #include "caps.h" @@ -66,8 +67,11 @@ static bool sigwinch; #endif +extern int build_buddylist; + static bool terminate_ui; GMainContext *main_context; +static guint refresh_timeout_id; static struct termios *backup_termios; @@ -377,6 +381,13 @@ return keyboard_activity(); } +static gboolean refresh_timeout_cb(gpointer data) { + // Only called once, to trigger a refresh if needed + // so reset ID and return false. + refresh_timeout_id = 0; + return FALSE; +} + static GSourceFuncs mcabber_source_funcs = { mcabber_source_prepare, mcabber_source_check, @@ -483,6 +494,10 @@ } } + /* Initialize buddylist update timestamp */ + struct timespec last_ui_update; + clock_gettime(CLOCK_MONOTONIC, &last_ui_update); + /* Initialize PGP system We do it before ncurses initialization because we may need to request a passphrase. */ @@ -555,6 +570,9 @@ scr_LogPrint(LPRINT_DEBUG, "Entering into main loop..."); while(!terminate_ui) { + int64_t timediff; + struct timespec now; + if (g_main_context_iteration(main_context, TRUE) == FALSE) keyboard_activity(); #ifdef USE_SIGWINCH @@ -563,9 +581,36 @@ sigwinch = FALSE; } #endif - if (update_roster) - scr_draw_roster(); - scr_do_update(); + + // Compute time in ms since last buddylist/screen update + clock_gettime(CLOCK_MONOTONIC, &now); + timediff = (((now.tv_sec - last_ui_update.tv_sec) * 1.0e9) + + (now.tv_nsec - last_ui_update.tv_nsec)) / 1.0e6; + + if (timediff <= 200) { + // Trigger a timeout in 1s to make sure no refresh will be missed + if (!refresh_timeout_id) { + refresh_timeout_id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, + 1, refresh_timeout_cb, NULL, NULL); + } + } else if ((build_buddylist || update_roster)) { + // More than 200ms + if (build_buddylist || update_roster) { + if (build_buddylist) { + buddylist_build(); + update_roster = TRUE; + } + if (update_roster) { + scr_draw_roster(); + scr_do_update(); + last_ui_update = now; + } + } else { + // No roster change; minimum screen update + update_panels(); + doupdate(); + } + } } g_source_destroy(mc_source);