You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by rj...@apache.org on 2015/03/10 11:37:33 UTC

svn commit: r1665454 - in /tomcat/jk/trunk: native/common/ xdocs/miscellaneous/

Author: rjung
Date: Tue Mar 10 10:37:33 2015
New Revision: 1665454

URL: http://svn.apache.org/r1665454
Log:
Reduce lock contention during maintenance function.
This was observable when using a big number of AJP13
and LB workers. 

Modified:
    tomcat/jk/trunk/native/common/jk_ajp_common.c
    tomcat/jk/trunk/native/common/jk_ajp_common.h
    tomcat/jk/trunk/native/common/jk_lb_worker.c
    tomcat/jk/trunk/native/common/jk_lb_worker.h
    tomcat/jk/trunk/native/common/jk_service.h
    tomcat/jk/trunk/native/common/jk_shm.c
    tomcat/jk/trunk/native/common/jk_shm.h
    tomcat/jk/trunk/native/common/jk_status.c
    tomcat/jk/trunk/native/common/jk_worker.c
    tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml

Modified: tomcat/jk/trunk/native/common/jk_ajp_common.c
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_ajp_common.c?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_ajp_common.c (original)
+++ tomcat/jk/trunk/native/common/jk_ajp_common.c Tue Mar 10 10:37:33 2015
@@ -3376,38 +3376,17 @@ int ajp_get_endpoint(jk_worker_t *pThis,
     return JK_FALSE;
 }
 
-int JK_METHOD ajp_maintain(jk_worker_t *pThis, time_t mstarted, jk_logger_t *l)
+int JK_METHOD ajp_maintain(jk_worker_t *pThis, time_t mstarted, int global, jk_logger_t *l)
 {
     JK_TRACE_ENTER(l);
 
     if (pThis && pThis->worker_private) {
         ajp_worker_t *aw = pThis->worker_private;
         int i;
-        long delta;
         unsigned int n = 0, k = 0, cnt = 0;
         unsigned int m, m_count = 0;
         jk_sock_t   *m_sock;
 
-        jk_shm_lock();
-
-        /* Now we check for global maintenance (once for all processes).
-         * Checking workers for idleness.
-         * Therefore we globally sync and we use a global timestamp.
-         * Since it's possible that we come here a few milliseconds
-         * before the interval has passed, we allow a little tolerance.
-         */
-        delta = (long)difftime(mstarted, aw->s->last_maintain_time) +
-                JK_AJP_MAINTAIN_TOLERANCE;
-        if (delta >= aw->maintain_time) {
-            aw->s->last_maintain_time = mstarted;
-            if (aw->s->state == JK_AJP_STATE_OK &&
-                aw->s->used == aw->s->used_snapshot)
-                aw->s->state = JK_AJP_STATE_IDLE;
-            aw->s->used_snapshot = aw->s->used;
-        }
-
-        jk_shm_unlock();
-
         /* Do connection pool maintenance only if timeouts or keepalives are set
          */
         if (aw->cache_timeout <= 0 &&

Modified: tomcat/jk/trunk/native/common/jk_ajp_common.h
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_ajp_common.h?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_ajp_common.h (original)
+++ tomcat/jk/trunk/native/common/jk_ajp_common.h Tue Mar 10 10:37:33 2015
@@ -47,10 +47,6 @@ extern "C"
 #define JK_AJP_STATE_TEXT_MAX           (JK_AJP_STATE_PROBE)
 #define JK_AJP_STATE_TEXT_DEF           (JK_AJP_STATE_TEXT_IDLE)
 
-/* We accept doing global maintenance if we are */
-/* JK_AJP_MAINTAIN_TOLERANCE seconds early. */
-#define JK_AJP_MAINTAIN_TOLERANCE (2)
-
 /*
  * Conditional request attributes
  *
@@ -475,7 +471,7 @@ int ajp_connection_tcp_send_message(ajp_
 int ajp_connection_tcp_get_message(ajp_endpoint_t * ae,
                                    jk_msg_buf_t *msg, jk_logger_t *l);
 
-int JK_METHOD ajp_maintain(jk_worker_t *pThis, time_t now, jk_logger_t *l);
+int JK_METHOD ajp_maintain(jk_worker_t *pThis, time_t now, int global, jk_logger_t *l);
 
 int JK_METHOD ajp_shutdown(jk_worker_t *pThis, jk_logger_t *l);
 

Modified: tomcat/jk/trunk/native/common/jk_lb_worker.c
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_lb_worker.c?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_lb_worker.c (original)
+++ tomcat/jk/trunk/native/common/jk_lb_worker.c Tue Mar 10 10:37:33 2015
@@ -728,24 +728,15 @@ static jk_uint64_t decay_load(lb_worker_
     return curmax;
 }
 
-static int JK_METHOD maintain_workers(jk_worker_t *p, time_t now, jk_logger_t *l)
+static int JK_METHOD maintain_workers(jk_worker_t *p, time_t now, int global, jk_logger_t *l)
 {
     unsigned int i = 0;
     jk_uint64_t curmax = 0;
-    long delta;
 
     JK_TRACE_ENTER(l);
     if (p && p->worker_private) {
         lb_worker_t *lb = (lb_worker_t *)p->worker_private;
 
-        for (i = 0; i < lb->num_of_workers; i++) {
-            if (lb->lb_workers[i].worker->maintain) {
-                lb->lb_workers[i].worker->maintain(lb->lb_workers[i].worker, now, l);
-            }
-        }
-
-        jk_shm_lock();
-
         /* Now we check for global maintenance (once for all processes).
          * Checking workers for recovery and applying decay to the
          * load values should not be done by each process individually.
@@ -753,20 +744,42 @@ static int JK_METHOD maintain_workers(jk
          * Since it's possible that we come here a few milliseconds
          * before the interval has passed, we allow a little tolerance.
          */
-        delta = (long)difftime(now, lb->s->last_maintain_time) + JK_LB_MAINTAIN_TOLERANCE;
-        if (delta >= lb->maintain_time) {
+        if (global == JK_TRUE) {
+            time_t exponent = JK_LB_DECAY_MULT * difftime(now, lb->s->last_maintain_time) / lb->maintain_time;
             lb->s->last_maintain_time = now;
+
             if (JK_IS_DEBUG_LEVEL(l))
                 jk_log(l, JK_LOG_DEBUG,
                        "decay with 2^%d",
-                       JK_LB_DECAY_MULT * delta / lb->maintain_time);
-            curmax = decay_load(lb, JK_LB_DECAY_MULT * delta / lb->maintain_time, l);
+                       exponent);
+
+            jk_shm_lock();
+
+            curmax = decay_load(lb, exponent, l);
+
             if (!recover_workers(lb, curmax, now, l)) {
                 force_recovery(lb, NULL, l);
             }
+
+            /*
+             * Checking workers for idleness.
+             */
+            for (i = 0; i < lb->num_of_workers; i++) {
+                ajp_worker_t *aw = lb->lb_workers[i].worker->worker_private;
+                if (aw->s->state == JK_AJP_STATE_OK &&
+                    aw->s->used == aw->s->used_snapshot)
+                    aw->s->state = JK_AJP_STATE_IDLE;
+                aw->s->used_snapshot = aw->s->used;
+            }
+
+            jk_shm_unlock();
         }
 
-        jk_shm_unlock();
+        for (i = 0; i < lb->num_of_workers; i++) {
+            if (lb->lb_workers[i].worker->maintain) {
+                lb->lb_workers[i].worker->maintain(lb->lb_workers[i].worker, now, global, l);
+            }
+        }
 
     }
     else {

Modified: tomcat/jk/trunk/native/common/jk_lb_worker.h
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_lb_worker.h?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_lb_worker.h (original)
+++ tomcat/jk/trunk/native/common/jk_lb_worker.h Tue Mar 10 10:37:33 2015
@@ -127,9 +127,6 @@ extern "C"
 
 /* Time to wait before retry. */
 #define WAIT_BEFORE_RECOVER   (60)
-/* We accept doing global maintenance if we are */
-/* JK_LB_MAINTAIN_TOLERANCE seconds early. */
-#define JK_LB_MAINTAIN_TOLERANCE (2)
 /* We divide load values by 2^x during global maintenance. */
 /* The exponent x is JK_LB_DECAY_MULT*#MAINT_INTV_SINCE_LAST_MAINT */
 #define JK_LB_DECAY_MULT         (1)

Modified: tomcat/jk/trunk/native/common/jk_service.h
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_service.h?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_service.h (original)
+++ tomcat/jk/trunk/native/common/jk_service.h Tue Mar 10 10:37:33 2015
@@ -546,7 +546,7 @@ struct jk_worker
     /*
      * Maintain this worker.
      */
-    int (JK_METHOD * maintain) (jk_worker_t *w, time_t now, jk_logger_t *l);
+    int (JK_METHOD * maintain) (jk_worker_t *w, time_t now, int global, jk_logger_t *l);
 
     /*
      * Shut this worker down.

Modified: tomcat/jk/trunk/native/common/jk_shm.c
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_shm.c?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_shm.c (original)
+++ tomcat/jk/trunk/native/common/jk_shm.c Tue Mar 10 10:37:33 2015
@@ -42,6 +42,8 @@ struct jk_shm_header_data
     unsigned int pos;
     unsigned int childs;
     unsigned int workers;
+    unsigned int maintain_checking;
+    volatile time_t maintain_time;
 };
 
 typedef struct jk_shm_header_data jk_shm_header_data_t;
@@ -324,6 +326,8 @@ int jk_shm_open(const char *fname, int s
                JK_SHM_MAGIC_SIZ);
         jk_shmem.hdr->h.data.size = sz;
         jk_shmem.hdr->h.data.childs = 1;
+        jk_shmem.hdr->h.data.maintain_checking = 0;
+        jk_shmem.hdr->h.data.maintain_time = time(NULL);
     }
     else {
         jk_shmem.hdr->h.data.childs++;
@@ -659,6 +663,8 @@ static int do_shm_open(const char *fname
         memcpy(jk_shmem.hdr->h.data.magic, shm_signature, JK_SHM_MAGIC_SIZ);
         jk_shmem.hdr->h.data.size = sz;
         jk_shmem.hdr->h.data.childs = 1;
+        jk_shmem.hdr->h.data.maintain_checking = 0;
+        jk_shmem.hdr->h.data.maintain_time = time(NULL);
         if (JK_IS_DEBUG_LEVEL(l))
             jk_log(l, JK_LOG_DEBUG,
                    "Initialized shared memory %s size=%u free=%u addr=%#lx",
@@ -863,6 +869,23 @@ const char *jk_shm_name()
     return jk_shmem.filename;
 }
 
+int jk_shm_check_maintain(time_t trigger)
+{
+    int rv = JK_FALSE;
+    int maintain_checking = JK_ATOMIC_INCREMENT(&(jk_shmem.hdr->h.data.maintain_checking));
+    /* Another process (or thread) is already checking */
+    if (maintain_checking > 1) {
+        JK_ATOMIC_DECREMENT(&(jk_shmem.hdr->h.data.maintain_checking));
+        return rv;
+    }
+    if (jk_shmem.hdr->h.data.maintain_time < trigger) {
+        jk_shmem.hdr->h.data.maintain_time = time(NULL);
+        rv = JK_TRUE;
+    }
+    JK_ATOMIC_DECREMENT(&(jk_shmem.hdr->h.data.maintain_checking));
+    return rv;
+}
+
 int jk_shm_lock()
 {
     int rc = JK_TRUE;

Modified: tomcat/jk/trunk/native/common/jk_shm.h
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_shm.h?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_shm.h (original)
+++ tomcat/jk/trunk/native/common/jk_shm.h Tue Mar 10 10:37:33 2015
@@ -223,6 +223,8 @@ jk_shm_lb_sub_worker_t *jk_shm_alloc_lb_
 jk_shm_lb_worker_t *jk_shm_alloc_lb_worker(jk_pool_t *p, const char *name,
                                            jk_logger_t *l);
 
+int jk_shm_check_maintain(time_t trigger);
+
 /* Lock shared memory for thread safe access */
 int jk_shm_lock(void);
 

Modified: tomcat/jk/trunk/native/common/jk_status.c
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_status.c?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_status.c (original)
+++ tomcat/jk/trunk/native/common/jk_status.c Tue Mar 10 10:37:33 2015
@@ -2231,7 +2231,6 @@ static void display_worker_lb(jk_ws_serv
     map_count = count_maps(s, name, l);
     ms_min = lb->maintain_time - (int)difftime(now, lb->s->last_maintain_time);
     ms_max = ms_min + lb->maintain_time;
-    ms_min -= JK_LB_MAINTAIN_TOLERANCE;
     if (ms_min < 0) {
         ms_min = 0;
     }

Modified: tomcat/jk/trunk/native/common/jk_worker.c
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_worker.c?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_worker.c (original)
+++ tomcat/jk/trunk/native/common/jk_worker.c Tue Mar 10 10:37:33 2015
@@ -25,6 +25,7 @@
 #define _PLACE_WORKER_LIST_HERE
 #include "jk_worker_list.h"
 #include "jk_worker.h"
+#include "jk_shm.h"
 #include "jk_util.h"
 #include "jk_mt.h"
 
@@ -315,6 +316,7 @@ const char *wc_get_name_for_type(int typ
 void wc_maintain(jk_logger_t *l)
 {
     static time_t last_maintain = 0;
+    int needs_global_maintenance;
     int sz = jk_map_size(worker_map);
 
     JK_TRACE_ENTER(l);
@@ -325,7 +327,8 @@ void wc_maintain(jk_logger_t *l)
      * - time since last maintenance is big enough
      */
     if (sz > 0 && worker_maintain_time > 0 &&
-        difftime(time(NULL), last_maintain) >= worker_maintain_time) {
+        difftime(time(NULL), last_maintain) >= worker_maintain_time &&
+        !running_maintain) {
         int i;
         JK_ENTER_CS(&worker_lock);
         if (running_maintain ||
@@ -339,8 +342,10 @@ void wc_maintain(jk_logger_t *l)
          * the maintain until we are finished.
          */
         running_maintain = 1;
+        last_maintain = time(NULL);
         JK_LEAVE_CS(&worker_lock);
 
+        needs_global_maintenance = jk_shm_check_maintain(last_maintain - worker_maintain_time);
         for (i = 0; i < sz; i++) {
             jk_worker_t *w = jk_map_value_at(worker_map, i);
             if (w && w->maintain) {
@@ -348,11 +353,10 @@ void wc_maintain(jk_logger_t *l)
                     jk_log(l, JK_LOG_DEBUG,
                            "Maintaining worker %s",
                            jk_map_name_at(worker_map, i));
-                w->maintain(w, time(NULL), l);
+                w->maintain(w, time(NULL), needs_global_maintenance, l);
             }
         }
         JK_ENTER_CS(&worker_lock);
-        last_maintain = time(NULL);
         running_maintain = 0;
         JK_LEAVE_CS(&worker_lock);
     }

Modified: tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml?rev=1665454&r1=1665453&r2=1665454&view=diff
==============================================================================
--- tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml (original)
+++ tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml Tue Mar 10 10:37:33 2015
@@ -45,6 +45,11 @@
   <subsection name="Native">
     <changelog>
       <fix>
+        AJP, LB: Reduce lock contention during maintenance function.
+        This was observable when using a big number of AJP13 and LB
+        workers. (rjung)
+      </fix>
+      <fix>
         <bug>57060</bug>: Allow building from outside of source tree.
         Patch contributed by Petr Sumbera. (rjung)
       </fix>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org