From: Florian Forster Date: Sat, 17 Jan 2009 10:19:08 +0000 (+0100) Subject: network plugin: Make the receive thread even faster. X-Git-Tag: collectd-4.6.0~102 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=0b6de87f3d08326ee3200db8e16f3738df027ac0;hp=6667ac0ae4b48596df71998d38ef945b984102d3 network plugin: Make the receive thread even faster. On very busy systems, the thread apparently may not be scheduled often enough. So the receive buffer fills up quickly and data may be lost. This patch changes the `mutex_lock' to a `mutex_trylock' and data is only appended to the global receive-queue if the lock can be obtained without blocking. If the lock cannot be obtained without blocking, the data is instead appended to a private queue and that queue is appended to the global queue when the lock can next be taken. --- diff --git a/src/network.c b/src/network.c index 9e391bb2..34f89d96 100644 --- a/src/network.c +++ b/src/network.c @@ -1279,6 +1279,9 @@ static int network_receive (void) int i; int status; + receive_list_entry_t *private_list_head; + receive_list_entry_t *private_list_tail; + if (listen_sockets_num == 0) network_add_listen_socket (NULL, NULL); @@ -1288,6 +1291,9 @@ static int network_receive (void) return (-1); } + private_list_head = NULL; + private_list_tail = NULL; + while (listen_loop == 0) { status = poll (listen_sockets, listen_sockets_num, -1); @@ -1328,7 +1334,8 @@ static int network_receive (void) ERROR ("network plugin: malloc failed."); return (-1); } - memset (ent, '\0', sizeof (receive_list_entry_t)); + memset (ent, 0, sizeof (receive_list_entry_t)); + ent->next = NULL; /* Hopefully this be optimized out by the compiler. It * might help prevent stupid bugs in the future though. @@ -1338,22 +1345,49 @@ static int network_receive (void) memcpy (ent->data, buffer, buffer_len); ent->data_len = buffer_len; - pthread_mutex_lock (&receive_list_lock); - if (receive_list_head == NULL) - { - receive_list_head = ent; - receive_list_tail = ent; - } + if (private_list_head == NULL) + private_list_head = ent; else + private_list_tail->next = ent; + private_list_tail = ent; + + /* Do not block here. Blocking here has led to + * insufficient performance in the past. */ + if (pthread_mutex_trylock (&receive_list_lock) == 0) { - receive_list_tail->next = ent; - receive_list_tail = ent; + if (receive_list_head == NULL) + receive_list_head = private_list_head; + else + receive_list_tail->next = private_list_head; + receive_list_tail = private_list_tail; + + private_list_head = NULL; + private_list_tail = NULL; + + pthread_cond_signal (&receive_list_cond); + pthread_mutex_unlock (&receive_list_lock); } - pthread_cond_signal (&receive_list_cond); - pthread_mutex_unlock (&receive_list_lock); } /* for (listen_sockets) */ } /* while (listen_loop == 0) */ + /* Make sure everything is dispatched before exiting. */ + if (private_list_head != NULL) + { + pthread_mutex_lock (&receive_list_lock); + + if (receive_list_head == NULL) + receive_list_head = private_list_head; + else + receive_list_tail->next = private_list_head; + receive_list_tail = private_list_tail; + + private_list_head = NULL; + private_list_tail = NULL; + + pthread_cond_signal (&receive_list_cond); + pthread_mutex_unlock (&receive_list_lock); + } + return (0); }