Browse Source

* Improve google perf tools support

* Pass to event_add only copies of struct timeval to avoid timing problems
tags/0.2.7
Vsevolod Stakhov 15 years ago
parent
commit
b8c5174335
9 changed files with 90 additions and 36 deletions
  1. 16
    0
      CMakeLists.txt
  2. 4
    0
      config.h.in
  3. 22
    6
      src/buffer.c
  4. 2
    1
      src/controller.c
  5. 1
    0
      src/fuzzy_storage.c
  6. 2
    0
      src/lmtp.c
  7. 40
    2
      src/util.c
  8. 2
    0
      src/util.h
  9. 1
    27
      src/worker.c

+ 16
- 0
CMakeLists.txt View File

ENDIF(ENABLE_PROFILING MATCHES "ON") ENDIF(ENABLE_PROFILING MATCHES "ON")


IF(ENABLE_GPERF_TOOLS 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) SET(WITH_GPERF_TOOLS 1)
ENDIF(ENABLE_GPERF_TOOLS MATCHES "ON") ENDIF(ENABLE_GPERF_TOOLS MATCHES "ON")


${CLASSIFIERSSRC} ${PLUGINSSRC} ${YACC_OUTPUT} ${CLASSIFIERSSRC} ${PLUGINSSRC} ${YACC_OUTPUT}
${LEX_OUTPUT}) ${LEX_OUTPUT})
SET_TARGET_PROPERTIES(rspamd PROPERTIES LINKER_LANGUAGE C) 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}) SET_TARGET_PROPERTIES(rspamd PROPERTIES VERSION ${RSPAMD_VERSION})


IF(ENABLE_PERL MATCHES "ON") IF(ENABLE_PERL MATCHES "ON")

+ 4
- 0
config.h.in View File

#define HAVE_SETLOCALE 1 #define HAVE_SETLOCALE 1
#endif #endif


#ifdef WITH_GPERF_TOOLS
#include <google/profiler.h>
#endif

#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <event.h> #include <event.h>

+ 22
- 6
src/buffer.c View File

GList *cur; GList *cur;
GError *err; GError *err;
rspamd_buffer_t *buf; rspamd_buffer_t *buf;
struct timeval *ntv;
ssize_t r; ssize_t r;


/* Fix order */ /* Fix order */
/* Wait for other event */ /* Wait for other event */
event_del (d->ev); event_del (d->ev);
event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); 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; return;
} }
cur = g_list_next (cur); cur = g_list_next (cur);
event_del (d->ev); event_del (d->ev);
event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); 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 { else {
/* Plan other write event */ /* Plan other write event */
event_del (d->ev); event_del (d->ev);
event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); 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);
} }
} }


{ {
rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *)arg; rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *)arg;
GError *err; GError *err;
struct timeval *ntv;


msg_debug ("dispatcher_cb: in dispatcher callback, what: %d, fd: %d", (int)what, fd); msg_debug ("dispatcher_cb: in dispatcher callback, what: %d, fd: %d", (int)what, fd);


if (d->out_buffers == NULL) { if (d->out_buffers == NULL) {
event_del (d->ev); event_del (d->ev);
event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); 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 { else {
write_buffers (fd, d); write_buffers (fd, d);
struct timeval *tv, void *user_data) struct timeval *tv, void *user_data)
{ {
rspamd_io_dispatcher_t *new; rspamd_io_dispatcher_t *new;
struct timeval *ntv;


if (fd == -1) { if (fd == -1) {
return NULL; return NULL;
new->fd = fd; new->fd = fd;


event_set (new->ev, fd, EV_WRITE, dispatcher_cb, (void *)new); 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; return new;
} }
size_t len, gboolean delayed, gboolean allocated) size_t len, gboolean delayed, gboolean allocated)
{ {
rspamd_buffer_t *newbuf; rspamd_buffer_t *newbuf;
struct timeval *ntv;


newbuf = memory_pool_alloc (d->pool, sizeof (rspamd_buffer_t)); newbuf = memory_pool_alloc (d->pool, sizeof (rspamd_buffer_t));
if (!allocated) { if (!allocated) {
msg_debug ("rspamd_dispatcher_write: plan write event"); msg_debug ("rspamd_dispatcher_write: plan write event");
event_del (d->ev); event_del (d->ev);
event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); 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);
} }
} }



+ 2
- 1
src/controller.c View File



/* Send SIGUSR2 to parent */ /* Send SIGUSR2 to parent */
kill (getppid (), SIGUSR2); kill (getppid (), SIGUSR2);


gperf_profiler_init (worker->srv->cfg, "controller");
event_loop (0); event_loop (0);


exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);

+ 1
- 0
src/fuzzy_storage.c View File

event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)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); event_add(&worker->bind_ev, NULL);


gperf_profiler_init (worker->srv->cfg, "fuzzy");


event_loop (0); event_loop (0);
exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);

+ 2
- 0
src/lmtp.c View File

io_tv.tv_sec = WORKER_IO_TIMEOUT; io_tv.tv_sec = WORKER_IO_TIMEOUT;
io_tv.tv_usec = 0; io_tv.tv_usec = 0;


gperf_profiler_init (worker->srv->cfg, "lmtp");

event_loop (0); event_loop (0);
exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);
} }

+ 40
- 2
src/util.c View File

#include "cfg_file.h" #include "cfg_file.h"
#include "main.h" #include "main.h"


#ifdef RSPAMD_MAIN
sig_atomic_t do_reopen_log = 0; sig_atomic_t do_reopen_log = 0;
extern rspamd_hash_t *counters; extern rspamd_hash_t *counters;
#endif


struct logger_params { struct logger_params {
GLogFunc log_func; GLogFunc log_func;
int int
reopen_log (struct config_file *cfg) reopen_log (struct config_file *cfg)
{ {
#ifdef RSPAMD_MAIN
do_reopen_log = 0; do_reopen_log = 0;
#endif
close_log (cfg); close_log (cfg);
return open_log (cfg); return open_log (cfg);
} }
syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg)
{ {
struct config_file *cfg = (struct config_file *)arg; struct config_file *cfg = (struct config_file *)arg;
#ifdef RSPAMD_MAIN
if (do_reopen_log) { if (do_reopen_log) {
reopen_log (cfg); reopen_log (cfg);
} }
#endif


if (log_level <= cfg->log_level) { if (log_level <= cfg->log_level) {
if (log_level >= G_LOG_LEVEL_DEBUG) { if (log_level >= G_LOG_LEVEL_DEBUG) {
if (cfg->log_fd == -1) { if (cfg->log_fd == -1) {
return; return;
} }
#ifdef RSPAMD_MAIN
if (do_reopen_log) { if (do_reopen_log) {
reopen_log (cfg); reopen_log (cfg);
} }
#endif


if (log_level <= cfg->log_level) { if (log_level <= cfg->log_level) {
now = time (NULL); now = time (NULL);
double double
set_counter (const char *name, long int value) set_counter (const char *name, long int value)
{ {
#ifdef RSPAMD_MAIN
struct counter_data *cd; struct counter_data *cd;
double alpha; double alpha;
char *key; char *key;
} }


return cd->value; return cd->value;
#else
return 0;
#endif
} }


#ifndef g_tolower #ifndef g_tolower
return h; 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 * vi:ts=4
*/ */

+ 2
- 0
src/util.h View File

guint rspamd_strcase_hash (gconstpointer key); guint rspamd_strcase_hash (gconstpointer key);
gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2); gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2);


void gperf_profiler_init (struct config_file *cfg, const char *descr);



#endif #endif

+ 1
- 27
src/worker.c View File



#ifdef WITH_GPERF_TOOLS #ifdef WITH_GPERF_TOOLS
#include <glib/gprintf.h> #include <glib/gprintf.h>
/* Declare prototypes */
int ProfilerStart (u_char* fname);
void ProfilerStop (void);
void ProfilerRegisterThread (void);
#endif #endif


static struct timeval io_tv; static struct timeval io_tv;
monstartup ((u_long) &_start, (u_long) &etext); monstartup ((u_long) &_start, (u_long) &etext);
#endif #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 (); worker->srv->pid = getpid ();



Loading…
Cancel
Save