Hi

utime2gmt uses surprisingly much cpu, almost 10% according to gprof. It's 
fairly optimized, but it's called often with the same arguments.
So let's add a cache for it.

In the worst case (no cache hit ever), the overhead for utime2gmt is little 
less than 1%.
In the best case (cache hits always), drops utime2gmt cpu usage from 9.6% to 
1.2%.

Helps in mixed usage, since often accessed pages like the index page stay in 
the cache.

- Lauri
>From 731bb8ef992ee6257b6b2595a9d9a5c793fa3853 Mon Sep 17 00:00:00 2001
From: Lauri Kasanen <[email protected]>
Date: Tue, 15 May 2012 14:49:15 +0300
Subject: [PATCH] utils: Add a gmt text cache for utime2gmt

In the worst case (no cache hit ever), the overhead for utime2gmt is little 
less than 1%.
In the best case (cache hits always), drops utime2gmt cpu usage from 9.6% to 
1.2%.

Helps in mixed usage, since often accessed pages like the index page stay in the
cache.

Signed-off-by: Lauri Kasanen <[email protected]>
---
 src/include/mk_cache.h |    1 +
 src/include/mk_utils.h |    9 ++++++++-
 src/mk_cache.c         |    7 ++++++-
 src/mk_utils.c         |   40 +++++++++++++++++++++++++++++++++++++++-
 4 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/src/include/mk_cache.h b/src/include/mk_cache.h
index d261234..dedd05b 100644
--- a/src/include/mk_cache.h
+++ b/src/include/mk_cache.h
@@ -31,6 +31,7 @@ pthread_key_t mk_cache_header_cl;
 pthread_key_t mk_cache_header_ka;
 pthread_key_t mk_cache_header_ka_max;
 pthread_key_t mk_cache_utils_gmtime;
+pthread_key_t mk_cache_utils_gmt_text;
 
 struct mk_cache_date_t
 {
diff --git a/src/include/mk_utils.h b/src/include/mk_utils.h
index ba45621..3a15ace 100644
--- a/src/include/mk_utils.h
+++ b/src/include/mk_utils.h
@@ -36,6 +36,14 @@
 #include "mk_memory.h"
 #include "mk_list.h"
 
+#define MK_GMT_CACHES 10
+
+struct mk_gmt_cache {
+    time_t time;
+    char text[32];
+    unsigned long long hits;
+};
+
 /* Trace definitions */
 #ifdef TRACE
 
@@ -45,7 +53,6 @@
 
 #define MK_TRACE(...) mk_utils_trace(MK_TRACE_COMP_CORE, MK_TRACE_CORE, \
                                      __FUNCTION__, __FILE__, __LINE__, 
__VA_ARGS__)
-
 #include "mk_plugin.h"
 
 char *env_trace_filter;
diff --git a/src/mk_cache.c b/src/mk_cache.c
index 26a1525..82eea6a 100644
--- a/src/mk_cache.c
+++ b/src/mk_cache.c
@@ -41,7 +41,8 @@ void mk_cache_thread_init()
 
     struct tm *cache_utils_gmtime;
     struct mk_iov *cache_iov_header;
-    
+    struct mk_gmt_cache *cache_utils_gmt_text;
+
     /* Cache header request -> last modified */
     cache_header_lm = mk_mem_malloc_z(sizeof(mk_pointer));
     cache_header_lm->data = mk_mem_malloc_z(32);
@@ -74,6 +75,10 @@ void mk_cache_thread_init()
     /* Cache gmtime buffer */
     cache_utils_gmtime = mk_mem_malloc(sizeof(struct tm));
     pthread_setspecific(mk_cache_utils_gmtime, (void *) cache_utils_gmtime);
+
+    /* Cache the most used text representations of utime2gmt */
+    cache_utils_gmt_text = mk_mem_malloc_z(sizeof(struct mk_gmt_cache) * 
MK_GMT_CACHES);
+    pthread_setspecific(mk_cache_utils_gmt_text, (void *) 
cache_utils_gmt_text);
 }
 
 void *mk_cache_get(pthread_key_t key)
diff --git a/src/mk_utils.c b/src/mk_utils.c
index e8a8f87..ec26836 100644
--- a/src/mk_utils.c
+++ b/src/mk_utils.c
@@ -54,6 +54,37 @@ static const char *mk_date_wd[7]  = {"Sun", "Mon", "Tue", 
"Wed", "Thu", "Fri", "
 static const char *mk_date_ym[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 
"Jul",
                                      "Aug", "Sep", "Oct", "Nov", "Dec"};
 
+static int mk_utils_gmt_cache_get(char **data, time_t date)
+{
+    unsigned int i;
+    struct mk_gmt_cache *gcache = mk_cache_get(mk_cache_utils_gmt_text);
+
+    for (i = 0; i < MK_GMT_CACHES; i++) {
+        if (date == gcache[i].time) {
+            memcpy(*data, gcache[i].text, 32);
+            gcache[i].hits++;
+            return MK_TRUE;
+        }
+    }
+
+    return MK_FALSE;
+}
+
+static void mk_utils_gmt_cache_add(char *data, time_t time)
+{
+    unsigned int i, min = 0;
+    struct mk_gmt_cache *gcache = mk_cache_get(mk_cache_utils_gmt_text);
+
+    for (i = 1; i < MK_GMT_CACHES; i++) {
+        if (gcache[i].hits < gcache[min].hits)
+            min = i;
+    }
+
+    gcache[min].hits = 1;
+    gcache[min].time = time;
+    memcpy(gcache[min].text, data, 32);
+}
+
 /*
  *This function given a unix time, set in a mk_pointer
  * the date in the RFC1123 format like:
@@ -64,7 +95,7 @@ static const char *mk_date_ym[12] = {"Jan", "Feb", "Mar", 
"Apr", "May", "Jun", "
  */
 int mk_utils_utime2gmt(char **data, time_t date)
 {
-    int size = 31;
+    const int size = 31;
     unsigned int year;
     char *buf=0;
     struct tm *gtm;
@@ -75,6 +106,11 @@ int mk_utils_utime2gmt(char **data, time_t date)
         }
     }
 
+    /* Maybe it's converted already? */
+    if (mk_utils_gmt_cache_get(data, date) == MK_TRUE) {
+        return size;
+    }
+
     /* Convert unix time to struct tm */
     gtm = mk_cache_get(mk_cache_utils_gmtime);
 
@@ -139,6 +175,8 @@ int mk_utils_utime2gmt(char **data, time_t date)
     *buf++ = '\n';
     *buf++ = '\0';
 
+    mk_utils_gmt_cache_add(*data, date);
+
     /* Set mk_pointer data len */
     return size;
 }
-- 
1.7.2.1

_______________________________________________
Monkey mailing list
[email protected]
http://lists.monkey-project.com/listinfo/monkey

Reply via email to