Now do garbage collection every second.
authorDave West <davew@uncensored.citadel.org>
Tue, 27 Nov 2007 01:21:13 +0000 (01:21 +0000)
committerDave West <davew@uncensored.citadel.org>
Tue, 27 Nov 2007 01:21:13 +0000 (01:21 +0000)
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
citadel/server_main.c
citadel/sysdep.c
citadel/sysdep_decls.h

index cc27e4363c2d923dfd21c6f787a5f3b5ddc09359..dac9d7a9b6299854cb1fe597122017ee67230163 100644 (file)
@@ -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");
 }
 
index 74c282673646fa73088a5f5995fba368dc68ad63..85cea680b1a67790d6e3236c11336aa8b6554f0b 100644 (file)
@@ -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
         */
index 6c5ce46a080b7cf26051c981bdf4cd814633f475..f1ce1f24ea7e65a9b780ff5a236f9dbd78bbe703 100644 (file)
@@ -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);
 }
 
 
index 1b000f7b267205806021d1efeb1802fd4282a10c..f6b5b8d92c61eb2b540ccec0cdc77936746a6171 100644 (file)
@@ -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 {