comparison 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
comparison
equal deleted inserted replaced
2280:f1eebfdd6db7 2281:1bb9002801e5
26 #include <sys/types.h> 26 #include <sys/types.h>
27 #include <sys/wait.h> 27 #include <sys/wait.h>
28 #include <glib.h> 28 #include <glib.h>
29 #include <config.h> 29 #include <config.h>
30 #include <poll.h> 30 #include <poll.h>
31 #include <time.h>
31 #include <errno.h> 32 #include <errno.h>
32 33
33 #include "caps.h" 34 #include "caps.h"
34 #include "screen.h" 35 #include "screen.h"
35 #include "settings.h" 36 #include "settings.h"
64 #ifdef USE_SIGWINCH 65 #ifdef USE_SIGWINCH
65 void sigwinch_resize(void); 66 void sigwinch_resize(void);
66 static bool sigwinch; 67 static bool sigwinch;
67 #endif 68 #endif
68 69
70 extern int build_buddylist;
71
69 static bool terminate_ui; 72 static bool terminate_ui;
70 GMainContext *main_context; 73 GMainContext *main_context;
74 static guint refresh_timeout_id;
71 75
72 static struct termios *backup_termios; 76 static struct termios *backup_termios;
73 77
74 char *mcabber_version(void) 78 char *mcabber_version(void)
75 { 79 {
375 static gboolean mcabber_source_dispatch(GSource *source, GSourceFunc callback, 379 static gboolean mcabber_source_dispatch(GSource *source, GSourceFunc callback,
376 gpointer udata) { 380 gpointer udata) {
377 return keyboard_activity(); 381 return keyboard_activity();
378 } 382 }
379 383
384 static gboolean refresh_timeout_cb(gpointer data) {
385 // Only called once, to trigger a refresh if needed
386 // so reset ID and return false.
387 refresh_timeout_id = 0;
388 return FALSE;
389 }
390
380 static GSourceFuncs mcabber_source_funcs = { 391 static GSourceFuncs mcabber_source_funcs = {
381 mcabber_source_prepare, 392 mcabber_source_prepare,
382 mcabber_source_check, 393 mcabber_source_check,
383 mcabber_source_dispatch, 394 mcabber_source_dispatch,
384 NULL, 395 NULL,
481 settings_set(SETTINGS_TYPE_OPTION, "password", pwd); 492 settings_set(SETTINGS_TYPE_OPTION, "password", pwd);
482 g_free(pwd); 493 g_free(pwd);
483 } 494 }
484 } 495 }
485 496
497 /* Initialize buddylist update timestamp */
498 struct timespec last_ui_update;
499 clock_gettime(CLOCK_MONOTONIC, &last_ui_update);
500
486 /* Initialize PGP system 501 /* Initialize PGP system
487 We do it before ncurses initialization because we may need to request 502 We do it before ncurses initialization because we may need to request
488 a passphrase. */ 503 a passphrase. */
489 if (settings_opt_get_int("pgp")) 504 if (settings_opt_get_int("pgp"))
490 main_init_pgp(); 505 main_init_pgp();
553 g_source_attach(mc_source, main_context); 568 g_source_attach(mc_source, main_context);
554 569
555 scr_LogPrint(LPRINT_DEBUG, "Entering into main loop..."); 570 scr_LogPrint(LPRINT_DEBUG, "Entering into main loop...");
556 571
557 while(!terminate_ui) { 572 while(!terminate_ui) {
573 int64_t timediff;
574 struct timespec now;
575
558 if (g_main_context_iteration(main_context, TRUE) == FALSE) 576 if (g_main_context_iteration(main_context, TRUE) == FALSE)
559 keyboard_activity(); 577 keyboard_activity();
560 #ifdef USE_SIGWINCH 578 #ifdef USE_SIGWINCH
561 if (sigwinch) { 579 if (sigwinch) {
562 sigwinch_resize(); 580 sigwinch_resize();
563 sigwinch = FALSE; 581 sigwinch = FALSE;
564 } 582 }
565 #endif 583 #endif
566 if (update_roster) 584
567 scr_draw_roster(); 585 // Compute time in ms since last buddylist/screen update
568 scr_do_update(); 586 clock_gettime(CLOCK_MONOTONIC, &now);
587 timediff = (((now.tv_sec - last_ui_update.tv_sec) * 1.0e9) +
588 (now.tv_nsec - last_ui_update.tv_nsec)) / 1.0e6;
589
590 if (timediff <= 200) {
591 // Trigger a timeout in 1s to make sure no refresh will be missed
592 if (!refresh_timeout_id) {
593 refresh_timeout_id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
594 1, refresh_timeout_cb, NULL, NULL);
595 }
596 } else if ((build_buddylist || update_roster)) {
597 // More than 200ms
598 if (build_buddylist || update_roster) {
599 if (build_buddylist) {
600 buddylist_build();
601 update_roster = TRUE;
602 }
603 if (update_roster) {
604 scr_draw_roster();
605 scr_do_update();
606 last_ui_update = now;
607 }
608 } else {
609 // No roster change; minimum screen update
610 update_panels();
611 doupdate();
612 }
613 }
569 } 614 }
570 615
571 g_source_destroy(mc_source); 616 g_source_destroy(mc_source);
572 g_source_unref(mc_source); 617 g_source_unref(mc_source);
573 } 618 }