From 6d9d7ee592ba14137a317afe5e6452adbecc6e98 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Nov 2012 13:45:49 +0100 Subject: [PATCH 1/3] lib/tsocket: disable the syscall optimization for recvfrom/readv by default We only do the optimization on recvfrom/readv if the caller asked for it. This is needed because in most cases we preferr to flush send buffers before receiving incoming requests. Signed-off-by: Stefan Metzmacher --- lib/tsocket/tsocket.h | 34 ++++++++++++++++++++++++ lib/tsocket/tsocket_bsd.c | 65 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h index 3aca536..56a741c 100644 --- a/lib/tsocket/tsocket.h +++ b/lib/tsocket/tsocket.h @@ -627,6 +627,23 @@ int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx, char *tsocket_address_unix_path(const struct tsocket_address *addr, TALLOC_CTX *mem_ctx); +/** + * @brief Request a syscall optimization for tdgram_recvfrom_send() + * + * This function is only used to reduce the amount of syscalls and + * optimize performance. You should only use this if you know + * what you're doing. + * + * @param[in] dgram The tdgram_context of a bsd socket, if this + * not a bsd socket the function does nothing. + * + * @param[in] on The boolean value to turn the optimization on and off. + * + * @see tdgram_recvfrom_send() + */ +void tdgram_bsd_optimize_recvfrom(struct tdgram_context *dgram, + bool on); + #ifdef DOXYGEN /** * @brief Create a tdgram_context for a ipv4 or ipv6 UDP communication. @@ -689,6 +706,23 @@ int _tdgram_unix_socket(const struct tsocket_address *local, #endif /** + * @brief Request a syscall optimization for tstream_readv_send() + * + * This function is only used to reduce the amount of syscalls and + * optimize performance. You should only use this if you know + * what you're doing. + * + * @param[in] stream The tstream_context of a bsd socket, if this + * not a bsd socket the function does nothing. + * + * @param[in] on The boolean value to turn the optimization on and off. + * + * @see tstream_readv_send() + */ +void tstream_bsd_optimize_readv(struct tstream_context *stream, + bool on); + +/** * @brief Connect async to a TCP endpoint and create a tstream_context for the * stream based communication. * diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c index 9e80065..4bf3743 100644 --- a/lib/tsocket/tsocket_bsd.c +++ b/lib/tsocket/tsocket_bsd.c @@ -654,6 +654,7 @@ struct tdgram_bsd { void *event_ptr; struct tevent_fd *fde; + bool optimize_recvfrom; void *readable_private; void (*readable_handler)(void *private_data); @@ -661,6 +662,21 @@ struct tdgram_bsd { void (*writeable_handler)(void *private_data); }; +void tdgram_bsd_optimize_recvfrom(struct tdgram_context *dgram, + bool on) +{ + struct tdgram_bsd *bsds = + talloc_get_type(_tdgram_context_data(dgram), + struct tdgram_bsd); + + if (bsds == NULL) { + /* not a bsd socket */ + return; + } + + bsds->optimize_recvfrom = on; +} + static void tdgram_bsd_fde_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, @@ -837,14 +853,25 @@ static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx, goto post; } + /* * this is a fast path, not waiting for the * socket to become explicit readable gains * about 10%-20% performance in benchmark tests. */ - tdgram_bsd_recvfrom_handler(req); - if (!tevent_req_is_in_progress(req)) { - goto post; + if (bsds->optimize_recvfrom) { + /* + * We only do the optimization on + * recvfrom if the caller asked for it. + * + * This is needed because in most cases + * we preferr to flush send buffers before + * receiving incoming requests. + */ + tdgram_bsd_recvfrom_handler(req); + if (!tevent_req_is_in_progress(req)) { + goto post; + } } ret = tdgram_bsd_set_readable_handler(bsds, ev, @@ -1400,6 +1427,7 @@ struct tstream_bsd { void *event_ptr; struct tevent_fd *fde; + bool optimize_readv; void *readable_private; void (*readable_handler)(void *private_data); @@ -1407,6 +1435,21 @@ struct tstream_bsd { void (*writeable_handler)(void *private_data); }; +void tstream_bsd_optimize_readv(struct tstream_context *stream, + bool on) +{ + struct tstream_bsd *bsds = + talloc_get_type(_tstream_context_data(stream), + struct tstream_bsd); + + if (bsds == NULL) { + /* not a bsd socket */ + return; + } + + bsds->optimize_readv = on; +} + static void tstream_bsd_fde_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, @@ -1619,9 +1662,19 @@ static struct tevent_req *tstream_bsd_readv_send(TALLOC_CTX *mem_ctx, * socket to become explicit readable gains * about 10%-20% performance in benchmark tests. */ - tstream_bsd_readv_handler(req); - if (!tevent_req_is_in_progress(req)) { - goto post; + if (bsds->optimize_readv) { + /* + * We only do the optimization on + * readv if the caller asked for it. + * + * This is needed because in most cases + * we preferr to flush send buffers before + * receiving incoming requests. + */ + tstream_bsd_readv_handler(req); + if (!tevent_req_is_in_progress(req)) { + goto post; + } } ret = tstream_bsd_set_readable_handler(bsds, ev, -- 1.7.9.5 From 2077220fadfdcfe5c976d34b681ae41f775cbc87 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Nov 2012 13:56:53 +0100 Subject: [PATCH 2/3] lib/tsocket: optimize syscalls in tstream_readv_pdu_send() Once we've got the first part of a pdu we try to optimize readv calls for the rest of the pdu. Signed-off-by: Stefan Metzmacher --- lib/tsocket/tsocket_helpers.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/tsocket/tsocket_helpers.c b/lib/tsocket/tsocket_helpers.c index 3a41a3e..b84d092 100644 --- a/lib/tsocket/tsocket_helpers.c +++ b/lib/tsocket/tsocket_helpers.c @@ -212,6 +212,19 @@ static void tstream_readv_pdu_ask_for_next_vector(struct tevent_req *req) size_t to_read = 0; size_t i; struct tevent_req *subreq; + bool optimize = false; + + if (state->count > 0) { + /* + * This is not the first time we asked for a vector, + * which means parts of the pdu already arrived. + * + * In this case it make sense to enable + * a syscall/performance optimization if the + * low level tstream implementation supports it. + */ + optimize = true; + } TALLOC_FREE(state->vector); state->count = 0; @@ -255,11 +268,24 @@ static void tstream_readv_pdu_ask_for_next_vector(struct tevent_req *req) return; } + if (optimize) { + /* + * If the low level stream is a bsd socket + * we will get syscall optimization. + * + * If it is not a bsd socket + * tstream_bsd_optimize_readv() just returns. + */ + tstream_bsd_optimize_readv(state->caller.stream, true); + } subreq = tstream_readv_send(state, state->caller.ev, state->caller.stream, state->vector, state->count); + if (optimize) { + tstream_bsd_optimize_readv(state->caller.stream, false); + } if (tevent_req_nomem(subreq, req)) { return; } -- 1.7.9.5 From 3b2bc92737c3fbe52c4a5ba5c259a4526b8ee83c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 Nov 2012 15:53:31 +0100 Subject: [PATCH 3/3] s3-aio_pthread: Optimize aio_pthread_handle_completion Read as much as we can --- source3/modules/vfs_aio_pthread.c | 58 ++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c index ceef822..6627811 100644 --- a/source3/modules/vfs_aio_pthread.c +++ b/source3/modules/vfs_aio_pthread.c @@ -74,6 +74,7 @@ static bool init_aio_threadpool(struct vfs_handle_struct *handle) struct fd_event *sock_event = NULL; int ret = 0; int num_threads; + int fd; if (pool) { return true; @@ -85,9 +86,14 @@ static bool init_aio_threadpool(struct vfs_handle_struct *handle) errno = ret; return false; } + + fd = pthreadpool_signal_fd(pool); + + set_blocking(fd, false); + sock_event = tevent_add_fd(server_event_context(), NULL, - pthreadpool_signal_fd(pool), + fd, TEVENT_FD_READ, aio_pthread_handle_completion, NULL); @@ -290,25 +296,43 @@ static void aio_pthread_handle_completion(struct event_context *event_ctx, return; } - ret = pthreadpool_finished_job(pool, &jobid); - if (ret) { - smb_panic("aio_pthread_handle_completion"); - return; - } + while (true) { + ret = pthreadpool_finished_job(pool, &jobid); - pd = find_private_data_by_jobid(jobid); - if (pd == NULL) { - DEBUG(1, ("aio_pthread_handle_completion cannot find jobid %d\n", - jobid)); - return; - } + if (ret == EINTR || ret == EAGAIN) { + return; + } +#ifdef EWOULDBLOCK + if (ret == EWOULDBLOCK) { + return; + } +#endif - aio_ex = (struct aio_extra *)pd->aiocb->aio_sigevent.sigev_value.sival_ptr; - smbd_aio_complete_aio_ex(aio_ex); + if (ret == ECANCELED) { + return; + } - DEBUG(10,("aio_pthread_handle_completion: jobid %d completed\n", - jobid )); - TALLOC_FREE(aio_ex); + if (ret) { + smb_panic("aio_pthread_handle_completion"); + return; + } + + pd = find_private_data_by_jobid(jobid); + if (pd == NULL) { + DEBUG(1, ("aio_pthread_handle_completion cannot find " + "jobid %d\n", jobid)); + return; + } + + aio_ex = (struct aio_extra *) + pd->aiocb->aio_sigevent.sigev_value.sival_ptr; + + smbd_aio_complete_aio_ex(aio_ex); + + DEBUG(10,("aio_pthread_handle_completion: jobid %d " + "completed\n", jobid )); + TALLOC_FREE(aio_ex); + } } /************************************************************************ -- 1.7.9.5