# HG changeset patch # User Mikael Berthe # Date 1474808844 -7200 # Node ID 1bb9002801e574006ae9894599ee4c79fc4e282d # Parent f1eebfdd6db755490db060b98cd743bb51867b97 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). diff -r f1eebfdd6db7 -r 1bb9002801e5 mcabber/mcabber/hooks.c --- a/mcabber/mcabber/hooks.c Sat Sep 24 12:31:13 2016 +0200 +++ b/mcabber/mcabber/hooks.c Sun Sep 25 15:07:24 2016 +0200 @@ -44,6 +44,8 @@ guint hid; } hook_list_data_t; +extern int build_buddylist; + static GHashTable *hk_handler_hash = NULL; // _new_hook_id() @@ -567,8 +569,7 @@ roster_setstatus(bjid, rn, prio, status, status_msg, timestamp, role_none, affil_none, NULL); - buddylist_build(); - update_roster = TRUE; + build_buddylist = TRUE; hlog_write_status(bjid, timestamp, status, status_msg); #ifdef MODULES_ENABLE diff -r f1eebfdd6db7 -r 1bb9002801e5 mcabber/mcabber/main.c --- 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 #include #include +#include #include #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); diff -r f1eebfdd6db7 -r 1bb9002801e5 mcabber/mcabber/roster.c --- a/mcabber/mcabber/roster.c Sat Sep 24 12:31:13 2016 +0200 +++ b/mcabber/mcabber/roster.c Sun Sep 25 15:07:24 2016 +0200 @@ -23,6 +23,8 @@ #include "utils.h" #include "hooks.h" +int build_buddylist; + extern void hlog_save_state(void); char *strrole[] = { /* Should match enum in roster.h */ @@ -1032,6 +1034,8 @@ // current_buddy initialization if (!current_buddy || (g_list_position(buddylist, current_buddy) == -1)) current_buddy = g_list_first(buddylist); + + build_buddylist = FALSE; } // buddy_hide_group(roster, hide) diff -r f1eebfdd6db7 -r 1bb9002801e5 mcabber/mcabber/screen.c --- a/mcabber/mcabber/screen.c Sat Sep 24 12:31:13 2016 +0200 +++ b/mcabber/mcabber/screen.c Sun Sep 25 15:07:24 2016 +0200 @@ -68,6 +68,8 @@ #define DEFAULT_ATTENTION_CHAR '!' +extern int build_buddylist; + const char *LocaleCharSet = "C"; static unsigned short int Log_Win_Height; @@ -2538,7 +2540,7 @@ } // We should rebuild the buddylist but not everytime if (!(buddylist_get_filter() & 1<