From 561072a2d377311c5d00a62b56171bb8a13611c2 Mon Sep 17 00:00:00 2001 From: Dave West Date: Tue, 27 Nov 2007 01:21:13 +0000 Subject: [PATCH] Now do garbage collection every second. Change the way load averages are calculated. Now calculate a load average for worker threads as well as the entire system. Display the load averages in the INFO command system then worker. Remove all the extra debug info from garbage collector. --- citadel/citserver.c | 5 ++- citadel/server_main.c | 10 ++++++ citadel/sysdep.c | 75 +++++++++++++++++++++++++++--------------- citadel/sysdep_decls.h | 3 ++ 4 files changed, 65 insertions(+), 28 deletions(-) diff --git a/citadel/citserver.c b/citadel/citserver.c index cc27e4363..dac9d7a9b 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -296,7 +296,10 @@ void cmd_info(void) { } cprintf("%s\n", config.c_default_cal_zone); - + /* Output load averages */ + cprintf("%f\n", CtdlThreadLoadAvg); + cprintf("%f\n", CtdlThreadWorkerAvg); + cprintf("000\n"); } diff --git a/citadel/server_main.c b/citadel/server_main.c index 74c282673..85cea680b 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -344,8 +344,18 @@ int main(int argc, char **argv) * This thread is now used for garbage collection of other threads in the thread list */ CtdlLogPrintf(CTDL_INFO, "Startup thread %d becoming garbage collector,\n", pthread_self()); + + /* Sleep 10 seconds before first garbage collection */ + CtdlThreadSleep(10); + while (CtdlThreadGetCount()) + { + ctdl_thread_internal_calc_loadavg(); + CtdlThreadSleep(1); ctdl_internal_thread_gc(); + if (CtdlThreadGetCount() <= 1) // Shutting down clean up the garbage collector + ctdl_internal_thread_gc(); + } /* * If the above loop exits we must be shutting down since we obviously have no threads */ diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 6c5ce46a0..f1ce1f24e 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -999,8 +999,8 @@ static pthread_cond_t thread_gc_cond = PTHREAD_COND_INITIALIZER; */ static pthread_t GC_thread; static char *CtdlThreadStates[CTDL_THREAD_LAST_STATE]; -double CtdlThreadLoadAvg; - +double CtdlThreadLoadAvg = 0; +double CtdlThreadWorkerAvg = 0; /* * Pinched the following bits regarding signals from Kannel.org */ @@ -1413,7 +1413,52 @@ static void ctdl_internal_thread_cleanup(void *arg) // CtdlThreadGC(); } +/* + * A quick function to show the load averages + */ +void ctdl_thread_internal_calc_loadavg(void) +{ + struct CtdlThreadNode *that_thread; + double load_avg, worker_avg; + int workers = 0; + begin_critical_section(S_THREAD_LIST); + that_thread = CtdlThreadList; + load_avg = 0; + worker_avg = 0; + while(that_thread) + { + /* Update load averages */ + ctdl_thread_internal_update_avgs(that_thread); + pthread_mutex_lock(&that_thread->ThreadMutex); + that_thread->load_avg = that_thread->avg_sleeping + that_thread->avg_running + that_thread->avg_blocked; + that_thread->load_avg = that_thread->avg_running / that_thread->load_avg / 100; + that_thread->avg_sleeping /= 2; + that_thread->avg_running /= 2; + that_thread->avg_blocked /= 2; + load_avg += that_thread->load_avg; + if (that_thread->flags & CTDLTHREAD_WORKER) + { + worker_avg += that_thread->load_avg; + workers++; + } +/* CtdlLogPrintf(CTDL_DEBUG, "CtdlThread, \"%s\" (%ld) \"%s\" %f %f %f %f.\n", + that_thread->name, + that_thread->tid, + CtdlThreadStates[that_thread->state], + that_thread->avg_sleeping, + that_thread->avg_running, + that_thread->avg_blocked, + that_thread->load_avg); +*/ + pthread_mutex_unlock(&that_thread->ThreadMutex); + that_thread = that_thread->next; + } + CtdlThreadLoadAvg = load_avg/num_threads; + CtdlThreadWorkerAvg = worker_avg/workers; +// CtdlLogPrintf(CTDL_INFO, "System load average %f, workers averag %f\n", CtdlThreadLoadAvg, CtdlThreadWorkerAvg); + end_critical_section(S_THREAD_LIST); +} /* @@ -1422,17 +1467,9 @@ static void ctdl_internal_thread_cleanup(void *arg) */ void ctdl_internal_thread_gc (void) { - struct CtdlThreadNode *this_thread, *that_thread = NULL; - double load_avg; + struct CtdlThreadNode *this_thread, *that_thread; int workers = 0; - /* - * Wait on the condition variable that tells us garbage collection is needed - * We wake up every 10 seconds just in case someone forgot to inform us of a thread exiting - */ - - CtdlThreadSleep(10); - /* Handle exiting of garbage collector thread */ if(num_threads == 1) CtdlThreadList->state = CTDL_THREAD_EXITED; @@ -1443,25 +1480,11 @@ void ctdl_internal_thread_gc (void) */ begin_critical_section(S_THREAD_LIST); this_thread = CtdlThreadList; - load_avg = 0; while(this_thread) { that_thread = this_thread; this_thread = this_thread->next; - /* Update load averages */ - ctdl_thread_internal_update_avgs(that_thread); - pthread_mutex_lock(&that_thread->ThreadMutex); - that_thread->load_avg = that_thread->avg_sleeping + that_thread->avg_running + that_thread->avg_blocked; - that_thread->load_avg = that_thread->avg_running / that_thread->load_avg / 100; - that_thread->avg_sleeping /= 10; - that_thread->avg_running /= 10; - that_thread->avg_blocked /= 10; - load_avg += that_thread->load_avg; - - CtdlLogPrintf(CTDL_DEBUG, "CtdlThread, \"%s\" (%ld) \"%s\" %f %f %f %f.\n", that_thread->name, that_thread->tid, CtdlThreadStates[that_thread->state], that_thread->avg_sleeping, that_thread->avg_running, that_thread->avg_blocked, that_thread->load_avg); - pthread_mutex_unlock(&that_thread->ThreadMutex); - /* Do we need to clean up this thread? */ if (that_thread->state != CTDL_THREAD_EXITED) { @@ -1524,9 +1547,7 @@ void ctdl_internal_thread_gc (void) CtdlLogPrintf(CTDL_EMERG, "Thread system PANIC, discrepancy in number of worker threads. Counted %d, should be %d.\n", workers, num_workers); return; } - CtdlThreadLoadAvg = load_avg/num_threads; end_critical_section(S_THREAD_LIST); - CtdlLogPrintf(CTDL_INFO, "System load average %f.\n", CtdlThreadLoadAvg); } diff --git a/citadel/sysdep_decls.h b/citadel/sysdep_decls.h index 1b000f7b2..f6b5b8d92 100644 --- a/citadel/sysdep_decls.h +++ b/citadel/sysdep_decls.h @@ -108,10 +108,13 @@ extern struct worker_node { */ #define CTDLTHREAD_BIGSTACK 0x0001 #define CTDLTHREAD_WORKER 0x0002 +extern double CtdlThreadLoadAvg; +extern double CtdlThreadWorkerAvg; void ctdl_internal_thread_gc (void); void ctdl_thread_internal_init(void); void ctdl_thread_internal_cleanup(void); +void ctdl_thread_internal_calc_loadavg(void); struct CtdlThreadNode *ctdl_internal_create_thread(char *name, long flags, void *(*thread_func) (void *arg), void *args); enum CtdlThreadState { -- 2.39.2