From 313ed5dc19898f7d2c868c828443bdf2227eb1a5 Mon Sep 17 00:00:00 2001 From: Sebastian Wilhelmi Date: Tue, 17 Apr 2001 11:48:45 +0000 Subject: [PATCH] Until now every thread pool always had at least one tread waiting to avoid 2001-04-17 Sebastian Wilhelmi * gthreadpool.c (g_thread_pool_thread_proxy): Until now every thread pool always had at least one tread waiting to avoid switching overhead in case a new task would be added soon after one finished. This however means a big waste of threads, if many mostly inactive thread pools are involved. Now such a waiting thread will only wait for half a second (This value is of course very randomly picked) and go to the global threadpool afterwards. MCVS: ---------------------------------------------------------------------- --- ChangeLog | 10 ++++++++ ChangeLog.pre-2-0 | 10 ++++++++ ChangeLog.pre-2-10 | 10 ++++++++ ChangeLog.pre-2-12 | 10 ++++++++ ChangeLog.pre-2-2 | 10 ++++++++ ChangeLog.pre-2-4 | 10 ++++++++ ChangeLog.pre-2-6 | 10 ++++++++ ChangeLog.pre-2-8 | 10 ++++++++ glib/gthreadpool.c | 68 ++++++++++++++++++++++++++++++++++++++++++------------ gthreadpool.c | 68 ++++++++++++++++++++++++++++++++++++++++++------------ 10 files changed, 186 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9a80b6..191a9b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index e9a80b6..191a9b6 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index e9a80b6..191a9b6 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index e9a80b6..191a9b6 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index e9a80b6..191a9b6 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index e9a80b6..191a9b6 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index e9a80b6..191a9b6 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index e9a80b6..191a9b6 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,13 @@ +2001-04-17 Sebastian Wilhelmi + + * gthreadpool.c (g_thread_pool_thread_proxy): Until now every + thread pool always had at least one tread waiting to avoid + switching overhead in case a new task would be added soon after + one finished. This however means a big waste of threads, if many + mostly inactive thread pools are involved. Now such a waiting + thread will only wait for half a second (This value is of course + very randomly picked) and go to the global threadpool afterwards. + Mon Apr 16 12:04:52 2001 Owen Taylor * configure.in: Remove warnings about conflicts with the diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c index 7f38503..af62d89 100644 --- a/glib/gthreadpool.c +++ b/glib/gthreadpool.c @@ -65,6 +65,7 @@ static void g_thread_pool_thread_proxy (gpointer data) { GRealThreadPool *pool = data; + gboolean watcher = FALSE; g_async_queue_lock (pool->queue); while (TRUE) @@ -76,23 +77,48 @@ g_thread_pool_thread_proxy (gpointer data) if (g_thread_should_run (pool, len)) { - task = g_async_queue_pop_unlocked (pool->queue); - - if (pool->num_threads > pool->max_threads && pool->max_threads != -1) - /* We are in fact a superfluous threads, so we go to the - * global pool and just hand the data further to the next one - * waiting in the queue */ + if (watcher) { - g_async_queue_push_unlocked (pool->queue, task); - goto_global_pool = TRUE; + /* This thread is actually not needed here, but it waits + * for some time anyway. If during that time a new + * request arrives, this saves process + * swicthes. Otherwise the thread will go to the global + * pool afterwards */ + GTimeVal end_time; + g_get_current_time (&end_time); + end_time.tv_usec += G_USEC_PER_SEC / 2; /* Halv a second */ + if (end_time.tv_usec >= G_USEC_PER_SEC) + { + end_time.tv_usec -= G_USEC_PER_SEC; + end_time.tv_sec += 1; + } + + task = g_async_queue_timed_pop_unlocked (pool->queue, &end_time); } - else if (pool->running || !pool->immediate) + else { - g_async_queue_unlock (pool->queue); - pool->pool.thread_func (task, pool->pool.user_data); - g_async_queue_lock (pool->queue); + task = g_async_queue_pop_unlocked (pool->queue); } + if (task) + { + watcher = FALSE; + if (pool->num_threads > pool->max_threads && + pool->max_threads != -1) + /* We are in fact a superfluous threads, so we go to + * the global pool and just hand the data further to + * the next one waiting in the queue */ + { + g_async_queue_push_unlocked (pool->queue, task); + goto_global_pool = TRUE; + } + else if (pool->running || !pool->immediate) + { + g_async_queue_unlock (pool->queue); + pool->pool.thread_func (task, pool->pool.user_data); + g_async_queue_lock (pool->queue); + } + } len = g_async_queue_length_unlocked (pool->queue); } @@ -101,9 +127,21 @@ g_thread_pool_thread_proxy (gpointer data) g_cond_broadcast (inform_cond); goto_global_pool = TRUE; } - else if (len >= 0) - /* At this pool there is no thread waiting */ - goto_global_pool = FALSE; + else if (len > 0) + { + /* At this pool there are no threads waiting, but tasks are. */ + goto_global_pool = FALSE; + } + else if (len == 0 && !watcher && !pool->pool.exclusive) + { + /* Here neither threads nor tasks are queued and we didn't + * just return from a timed wait. We now wait for a limited + * time at this pool for new tasks to avoid costly context + * switches. */ + goto_global_pool = FALSE; + watcher = TRUE; + } + if (goto_global_pool) { diff --git a/gthreadpool.c b/gthreadpool.c index 7f38503..af62d89 100644 --- a/gthreadpool.c +++ b/gthreadpool.c @@ -65,6 +65,7 @@ static void g_thread_pool_thread_proxy (gpointer data) { GRealThreadPool *pool = data; + gboolean watcher = FALSE; g_async_queue_lock (pool->queue); while (TRUE) @@ -76,23 +77,48 @@ g_thread_pool_thread_proxy (gpointer data) if (g_thread_should_run (pool, len)) { - task = g_async_queue_pop_unlocked (pool->queue); - - if (pool->num_threads > pool->max_threads && pool->max_threads != -1) - /* We are in fact a superfluous threads, so we go to the - * global pool and just hand the data further to the next one - * waiting in the queue */ + if (watcher) { - g_async_queue_push_unlocked (pool->queue, task); - goto_global_pool = TRUE; + /* This thread is actually not needed here, but it waits + * for some time anyway. If during that time a new + * request arrives, this saves process + * swicthes. Otherwise the thread will go to the global + * pool afterwards */ + GTimeVal end_time; + g_get_current_time (&end_time); + end_time.tv_usec += G_USEC_PER_SEC / 2; /* Halv a second */ + if (end_time.tv_usec >= G_USEC_PER_SEC) + { + end_time.tv_usec -= G_USEC_PER_SEC; + end_time.tv_sec += 1; + } + + task = g_async_queue_timed_pop_unlocked (pool->queue, &end_time); } - else if (pool->running || !pool->immediate) + else { - g_async_queue_unlock (pool->queue); - pool->pool.thread_func (task, pool->pool.user_data); - g_async_queue_lock (pool->queue); + task = g_async_queue_pop_unlocked (pool->queue); } + if (task) + { + watcher = FALSE; + if (pool->num_threads > pool->max_threads && + pool->max_threads != -1) + /* We are in fact a superfluous threads, so we go to + * the global pool and just hand the data further to + * the next one waiting in the queue */ + { + g_async_queue_push_unlocked (pool->queue, task); + goto_global_pool = TRUE; + } + else if (pool->running || !pool->immediate) + { + g_async_queue_unlock (pool->queue); + pool->pool.thread_func (task, pool->pool.user_data); + g_async_queue_lock (pool->queue); + } + } len = g_async_queue_length_unlocked (pool->queue); } @@ -101,9 +127,21 @@ g_thread_pool_thread_proxy (gpointer data) g_cond_broadcast (inform_cond); goto_global_pool = TRUE; } - else if (len >= 0) - /* At this pool there is no thread waiting */ - goto_global_pool = FALSE; + else if (len > 0) + { + /* At this pool there are no threads waiting, but tasks are. */ + goto_global_pool = FALSE; + } + else if (len == 0 && !watcher && !pool->pool.exclusive) + { + /* Here neither threads nor tasks are queued and we didn't + * just return from a timed wait. We now wait for a limited + * time at this pool for new tasks to avoid costly context + * switches. */ + goto_global_pool = FALSE; + watcher = TRUE; + } + if (goto_global_pool) { -- 2.7.4