Skip to content
Snippets Groups Projects
Commit 0840da4c authored by David Klempner's avatar David Klempner
Browse files

Move pollset_kick wfd creation/destruction out of freelist lock

This was an observed source of contention at higher thread counts where
we could overrun the freelist cap.
parent f229d4fd
No related branches found
No related tags found
No related merge requests found
...@@ -48,49 +48,49 @@ ...@@ -48,49 +48,49 @@
/* This implementation is based on a freelist of wakeup fds, with extra logic to /* This implementation is based on a freelist of wakeup fds, with extra logic to
* handle kicks while there is no attached fd. */ * handle kicks while there is no attached fd. */
/* TODO(klempner): Autosize this, and consider providing a way to disable the
* cap entirely on systems with large fd limits */
#define GRPC_MAX_CACHED_WFDS 50 #define GRPC_MAX_CACHED_WFDS 50
#define GRPC_WFD_LOW_WATERMARK 25
static grpc_kick_fd_info *fd_freelist = NULL; static grpc_kick_fd_info *fd_freelist = NULL;
static int fd_freelist_count = 0; static int fd_freelist_count = 0;
static gpr_mu fd_freelist_mu; static gpr_mu fd_freelist_mu;
static grpc_kick_fd_info *allocate_wfd(void) { static grpc_kick_fd_info *allocate_wfd(void) {
grpc_kick_fd_info *info; grpc_kick_fd_info *info = NULL;
gpr_mu_lock(&fd_freelist_mu); gpr_mu_lock(&fd_freelist_mu);
if (fd_freelist != NULL) { if (fd_freelist != NULL) {
info = fd_freelist; info = fd_freelist;
fd_freelist = fd_freelist->next; fd_freelist = fd_freelist->next;
--fd_freelist_count; --fd_freelist_count;
} else { }
gpr_mu_unlock(&fd_freelist_mu);
if (info == NULL) {
info = gpr_malloc(sizeof(*info)); info = gpr_malloc(sizeof(*info));
grpc_wakeup_fd_create(&info->wakeup_fd); grpc_wakeup_fd_create(&info->wakeup_fd);
info->next = NULL; info->next = NULL;
} }
gpr_mu_unlock(&fd_freelist_mu);
return info; return info;
} }
static void destroy_wfd(void) { static void destroy_wfd(grpc_kick_fd_info* wfd) {
/* assumes fd_freelist_mu is held */ grpc_wakeup_fd_destroy(&wfd->wakeup_fd);
grpc_kick_fd_info *current = fd_freelist; gpr_free(wfd);
fd_freelist = fd_freelist->next;
fd_freelist_count--;
grpc_wakeup_fd_destroy(&current->wakeup_fd);
gpr_free(current);
} }
static void free_wfd(grpc_kick_fd_info *fd_info) { static void free_wfd(grpc_kick_fd_info *fd_info) {
gpr_mu_lock(&fd_freelist_mu); gpr_mu_lock(&fd_freelist_mu);
fd_info->next = fd_freelist; if (fd_freelist_count < GRPC_MAX_CACHED_WFDS) {
fd_freelist = fd_info; fd_info->next = fd_freelist;
fd_freelist_count++; fd_freelist = fd_info;
if (fd_freelist_count > GRPC_MAX_CACHED_WFDS) { fd_freelist_count++;
while (fd_freelist_count > GRPC_WFD_LOW_WATERMARK) { fd_info = NULL;
destroy_wfd();
}
} }
gpr_mu_unlock(&fd_freelist_mu); gpr_mu_unlock(&fd_freelist_mu);
if (fd_info) {
destroy_wfd(fd_info);
}
} }
void grpc_pollset_kick_init(grpc_pollset_kick_state *kick_state) { void grpc_pollset_kick_init(grpc_pollset_kick_state *kick_state) {
...@@ -148,6 +148,11 @@ void grpc_pollset_kick_global_init(void) { ...@@ -148,6 +148,11 @@ void grpc_pollset_kick_global_init(void) {
} }
void grpc_pollset_kick_global_destroy(void) { void grpc_pollset_kick_global_destroy(void) {
while (fd_freelist != NULL) {
grpc_kick_fd_info *current = fd_freelist;
fd_freelist = fd_freelist->next;
destroy_wfd(current);
}
grpc_wakeup_fd_global_destroy(); grpc_wakeup_fd_global_destroy();
gpr_mu_destroy(&fd_freelist_mu); gpr_mu_destroy(&fd_freelist_mu);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment