zlogger: use cache for gettid() to reduce logging hot path overhead 72/283172/5
authorMarek Szyprowski <m.szyprowski@samsung.com>
Wed, 19 Oct 2022 15:48:35 +0000 (17:48 +0200)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Wed, 19 Oct 2022 16:22:56 +0000 (18:22 +0200)
Use thread local variable to cache gettid() calls and clear it with
pthread_atfork() hook. This reduces the logging hot path overhead by
avoiding any kernel calls.

On RPi4 this reduced a test message logging time (averaged) from 2.2us
to 0.8us.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Change-Id: I8ed74a4442d76183f2403861ac3c428fd9b5b051

src/libdlog/log_zero_copy.c

index 67054a5..60f1ed9 100644 (file)
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <pthread.h>
 
 #include <logcommon.h>
 #include <zero_copy_backend.h>
 static int g_fd;
 static char *g_shm_ptr[ZLOGGER_DEVICE_COUNT];
 _Thread_local uint16_t blk = 0;
+_Thread_local int g_tid = 0;
 
 extern int (*write_to_log)(log_id_t log_id, log_priority prio, const char *tag, const char *msg, struct timespec *tp_mono);
 extern void (*destroy_backend)(void);
 
+/* Use thread local cache for tid to speed-up logging hot path */
+static inline int gettid_cached(void)
+{
+       if (!g_tid)
+               g_tid = gettid();
+       return g_tid;
+}
+
+/*
+ * fork() doesn't clear/reinitialize thread local variables,
+ * so we need to do this from pthread_atfork() hooks
+ */
+static void clear_thread_locals(void)
+{
+       g_tid = 0;
+}
+
 static inline char *get_shared_memory(int dev_index)
 {
        if (dev_index < 0 || dev_index >= ZLOGGER_DEVICE_COUNT)
@@ -94,7 +113,7 @@ static int zero_copy_write(log_id_t log_id, log_priority prio, const char *tag,
         * for stdout logs though. */
 
        uint64_t ts = tp_mono ? to_zlog_clock(tp_mono) : get_zlog_clock();
-       const int tid = gettid();
+       const int tid = gettid_cached();
        size_t hd_size = sizeof(struct zlogger_entry);
        size_t prio_size = 1;
        size_t tag_size = strnlen(tag, ZLOGGER_TAG_MAX) + 1;
@@ -153,6 +172,12 @@ int __dlog_init_zero_copy(struct log_config *config)
        if (g_fd < 0)
                return -1;
 
+       /* properly handle thread local variables on fork() */
+       if (pthread_atfork(NULL, NULL, clear_thread_locals) != 0) {
+               close(g_fd);
+               return -1;
+       }
+
        for (int i = 0; i < ZLOGGER_DEVICE_COUNT; i++)
                g_shm_ptr[i] = MAP_FAILED;
 
@@ -169,4 +194,3 @@ int __dlog_init_zero_copy(struct log_config *config)
 
        return 0;
 }
-