From b8c51743357c4bc1fc5067dc0bd5e8992310c93d Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 25 Aug 2009 13:50:35 +0400 Subject: [PATCH] * Improve google perf tools support * Pass to event_add only copies of struct timeval to avoid timing problems --- CMakeLists.txt | 16 ++++++++++++++++ config.h.in | 4 ++++ src/buffer.c | 28 ++++++++++++++++++++++------ src/controller.c | 3 ++- src/fuzzy_storage.c | 1 + src/lmtp.c | 2 ++ src/util.c | 42 ++++++++++++++++++++++++++++++++++++++++-- src/util.h | 2 ++ src/worker.c | 28 +--------------------------- 9 files changed, 90 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3024a07d2..d52ee61ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,21 @@ IF(ENABLE_PROFILING MATCHES "ON") ENDIF(ENABLE_PROFILING MATCHES "ON") IF(ENABLE_GPERF_TOOLS MATCHES "ON") + FIND_PATH(GPERF_INCLUDE google/profiler.h PATHS /opt/include + /usr/include + /usr/local/include + DOC "Path where google perftools includes can be found") + INCLUDE_DIRECTORIES("${GPERF_INCLUDE}") + FIND_LIBRARY(GPERF_LIBRARY NAMES profiler PATHS /lib + /opt/lib + /usr/lib + /usr/local/lib + DOC "Path where the gperf library can be found") + IF(NOT GPERF_LIBRARY) + MESSAGE(FATAL_ERROR "gperf tools support is enabled but not found in system") + ENDIF(NOT GPERF_LIBRARY) + GET_FILENAME_COMPONENT(GPERF_PATH "${GPERF_LIBRARY}" PATH) + LINK_DIRECTORIES("${GPERF_PATH}") SET(WITH_GPERF_TOOLS 1) ENDIF(ENABLE_GPERF_TOOLS MATCHES "ON") @@ -429,6 +444,7 @@ ADD_EXECUTABLE(rspamd ${RSPAMDSRC} ${CONTRIBSRC} ${TOKENIZERSSRC} ${CLASSIFIERSSRC} ${PLUGINSSRC} ${YACC_OUTPUT} ${LEX_OUTPUT}) SET_TARGET_PROPERTIES(rspamd PROPERTIES LINKER_LANGUAGE C) +SET_TARGET_PROPERTIES(rspamd PROPERTIES COMPILE_FLAGS "-DRSPAMD_MAIN") SET_TARGET_PROPERTIES(rspamd PROPERTIES VERSION ${RSPAMD_VERSION}) IF(ENABLE_PERL MATCHES "ON") diff --git a/config.h.in b/config.h.in index 12593da61..0db410bb5 100644 --- a/config.h.in +++ b/config.h.in @@ -269,6 +269,10 @@ #define HAVE_SETLOCALE 1 #endif +#ifdef WITH_GPERF_TOOLS +#include +#endif + #include #include #include diff --git a/src/buffer.c b/src/buffer.c index f8d027307..d212fc220 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -44,6 +44,7 @@ write_buffers (int fd, rspamd_io_dispatcher_t *d) GList *cur; GError *err; rspamd_buffer_t *buf; + struct timeval *ntv; ssize_t r; /* Fix order */ @@ -87,7 +88,9 @@ write_buffers (int fd, rspamd_io_dispatcher_t *d) /* Wait for other event */ event_del (d->ev); event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); - event_add (d->ev, d->tv); + ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); + memcpy (ntv, d->tv, sizeof (struct timeval)); + event_add (d->ev, ntv); return; } cur = g_list_next (cur); @@ -111,13 +114,17 @@ write_buffers (int fd, rspamd_io_dispatcher_t *d) event_del (d->ev); event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); - event_add (d->ev, d->tv); + ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); + memcpy (ntv, d->tv, sizeof (struct timeval)); + event_add (d->ev, ntv); } else { /* Plan other write event */ event_del (d->ev); event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); - event_add (d->ev, d->tv); + ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); + memcpy (ntv, d->tv, sizeof (struct timeval)); + event_add (d->ev, ntv); } } @@ -257,6 +264,7 @@ dispatcher_cb (int fd, short what, void *arg) { rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *)arg; GError *err; + struct timeval *ntv; msg_debug ("dispatcher_cb: in dispatcher callback, what: %d, fd: %d", (int)what, fd); @@ -272,7 +280,9 @@ dispatcher_cb (int fd, short what, void *arg) if (d->out_buffers == NULL) { event_del (d->ev); event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); - event_add (d->ev, d->tv); + ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); + memcpy (ntv, d->tv, sizeof (struct timeval)); + event_add (d->ev, ntv); } else { write_buffers (fd, d); @@ -293,6 +303,7 @@ rspamd_create_dispatcher (int fd, enum io_policy policy, struct timeval *tv, void *user_data) { rspamd_io_dispatcher_t *new; + struct timeval *ntv; if (fd == -1) { return NULL; @@ -320,7 +331,9 @@ rspamd_create_dispatcher (int fd, enum io_policy policy, new->fd = fd; event_set (new->ev, fd, EV_WRITE, dispatcher_cb, (void *)new); - event_add (new->ev, new->tv); + ntv = memory_pool_alloc (new->pool, sizeof (struct timeval)); + memcpy (ntv, new->tv, sizeof (struct timeval)); + event_add (new->ev, ntv); return new; } @@ -378,6 +391,7 @@ rspamd_dispatcher_write (rspamd_io_dispatcher_t *d, size_t len, gboolean delayed, gboolean allocated) { rspamd_buffer_t *newbuf; + struct timeval *ntv; newbuf = memory_pool_alloc (d->pool, sizeof (rspamd_buffer_t)); if (!allocated) { @@ -401,7 +415,9 @@ rspamd_dispatcher_write (rspamd_io_dispatcher_t *d, msg_debug ("rspamd_dispatcher_write: plan write event"); event_del (d->ev); event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); - event_add (d->ev, d->tv); + ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); + memcpy (ntv, d->tv, sizeof (struct timeval)); + event_add (d->ev, ntv); } } diff --git a/src/controller.c b/src/controller.c index 65434c974..4196e16f0 100644 --- a/src/controller.c +++ b/src/controller.c @@ -627,8 +627,9 @@ start_controller (struct rspamd_worker *worker) /* Send SIGUSR2 to parent */ kill (getppid (), SIGUSR2); - + gperf_profiler_init (worker->srv->cfg, "controller"); + event_loop (0); exit (EXIT_SUCCESS); diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index 296e81562..53f3d9b16 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -478,6 +478,7 @@ start_fuzzy_storage (struct rspamd_worker *worker) event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)worker); event_add(&worker->bind_ev, NULL); + gperf_profiler_init (worker->srv->cfg, "fuzzy"); event_loop (0); exit (EXIT_SUCCESS); diff --git a/src/lmtp.c b/src/lmtp.c index 6554ba4f4..c3d5ab344 100644 --- a/src/lmtp.c +++ b/src/lmtp.c @@ -294,6 +294,8 @@ start_lmtp_worker (struct rspamd_worker *worker) io_tv.tv_sec = WORKER_IO_TIMEOUT; io_tv.tv_usec = 0; + gperf_profiler_init (worker->srv->cfg, "lmtp"); + event_loop (0); exit (EXIT_SUCCESS); } diff --git a/src/util.c b/src/util.c index 364e1b0a4..585aa5cb8 100644 --- a/src/util.c +++ b/src/util.c @@ -28,9 +28,10 @@ #include "cfg_file.h" #include "main.h" - +#ifdef RSPAMD_MAIN sig_atomic_t do_reopen_log = 0; extern rspamd_hash_t *counters; +#endif struct logger_params { GLogFunc log_func; @@ -669,7 +670,9 @@ rspamd_set_logger (GLogFunc func, struct config_file *cfg) int reopen_log (struct config_file *cfg) { +#ifdef RSPAMD_MAIN do_reopen_log = 0; +#endif close_log (cfg); return open_log (cfg); } @@ -692,9 +695,11 @@ void syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) { struct config_file *cfg = (struct config_file *)arg; +#ifdef RSPAMD_MAIN if (do_reopen_log) { reopen_log (cfg); } +#endif if (log_level <= cfg->log_level) { if (log_level >= G_LOG_LEVEL_DEBUG) { @@ -725,10 +730,11 @@ file_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gcha if (cfg->log_fd == -1) { return; } - +#ifdef RSPAMD_MAIN if (do_reopen_log) { reopen_log (cfg); } +#endif if (log_level <= cfg->log_level) { now = time (NULL); @@ -844,6 +850,7 @@ calculate_check_time (struct timespec *begin, int resolution) double set_counter (const char *name, long int value) { +#ifdef RSPAMD_MAIN struct counter_data *cd; double alpha; char *key; @@ -868,6 +875,9 @@ set_counter (const char *name, long int value) } return cd->value; +#else + return 0; +#endif } #ifndef g_tolower @@ -899,6 +909,34 @@ rspamd_strcase_hash (gconstpointer key) return h; } +void +gperf_profiler_init (struct config_file *cfg, const char *descr) +{ +#if defined(WITH_GPERF_TOOLS) && defined(MAIN_RSPAMD) + char prof_path[PATH_MAX]; + + if (getenv("CPUPROFILE")) { + + /* disable inherited Profiler enabled in master process */ + ProfilerStop (); + } + /* Try to create temp directory for gmon.out and chdir to it */ + if (cfg->profile_path == NULL) { + cfg->profile_path = g_strdup_printf ("%s/rspamd-profile", cfg->temp_dir); + } + + snprintf (prof_path, sizeof (prof_path), "%s-%s.%d", cfg->profile_path, descr, (int)getpid ()); + if (ProfilerStart (prof_path)) { + /* start ITIMER_PROF timer */ + ProfilerRegisterThread(); + } + else { + msg_warn ("gperf_frofiler_init: cannot start google perftools profiler"); + } + +#endif +} + /* * vi:ts=4 */ diff --git a/src/util.h b/src/util.h index d7665d462..139a44262 100644 --- a/src/util.h +++ b/src/util.h @@ -67,5 +67,7 @@ double set_counter (const char *name, long int value); guint rspamd_strcase_hash (gconstpointer key); gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2); +void gperf_profiler_init (struct config_file *cfg, const char *descr); + #endif diff --git a/src/worker.c b/src/worker.c index 4832c71fc..9e9b73938 100644 --- a/src/worker.c +++ b/src/worker.c @@ -48,10 +48,6 @@ extern PerlInterpreter *perl_interpreter; #ifdef WITH_GPERF_TOOLS #include -/* Declare prototypes */ -int ProfilerStart (u_char* fname); -void ProfilerStop (void); -void ProfilerRegisterThread (void); #endif static struct timeval io_tv; @@ -343,29 +339,7 @@ start_worker (struct rspamd_worker *worker) monstartup ((u_long) &_start, (u_long) &etext); #endif -#ifdef WITH_GPERF_TOOLS - char prof_path[PATH_MAX]; - - if (getenv("CPUPROFILE")) { - - /* disable inherited Profiler enabled in master process */ - ProfilerStop (); - } - /* Try to create temp directory for gmon.out and chdir to it */ - if (worker->srv->cfg->profile_path == NULL) { - worker->srv->cfg->profile_path = g_strdup_printf ("%s/rspamd-profile", worker->srv->cfg->temp_dir); - } - - snprintf (prof_path, sizeof (prof_path), "%s.%d", worker->srv->cfg->profile_path, (int)getpid ()); - if (ProfilerStart (prof_path)) { - /* start ITIMER_PROF timer */ - ProfilerRegisterThread(); - } - else { - msg_warn ("start_worker: cannot start google perftools profiler"); - } - -#endif + gperf_profiler_init (worker->srv->cfg, "worker"); worker->srv->pid = getpid (); -- 2.39.5