[Virtio-fs] [RFC][PATCH][v3] virtiofsd: virtiofsd: Use thread pool only after certain queue depth
Vivek Goyal
vgoyal at redhat.com
Tue May 4 15:18:41 UTC 2021
For low queue depth workloads, inline processing works well. But for
high queue depth (and multiple process/thread) workloads, parallel
processing of thread pool can benefit.
This patch provides a knob --thread-pool-threshold=<nr-requests>, which
uses a thread pool only if number of requests on virtqueue are more
than nr-requests. IOW, upto nr-requests, requests are processed inline
and anything more than nr-requests is sent for processing in thread
pool.
I have got good results with "--thread-pool-size=16 --thread-pool-threshold=3"
on my system.
Signed-off-by: Vivek Goyal <vgoyal at redhat.com>
---
Test results with this patch are available here.
https://github.com/rhvgoyal/virtiofs-tests/tree/master/performance-results/thread-pool-threshold/4-may-2021
Changes since v2:
- Renamed knob name to "--thread-pool-threshold"
- Started using GQueue instead of GList to keep a list of requests
received on virtqueue (Greg)
- When threshold is crossed only requests above threshold are sent to
thread pool. Rest are still processed inline. (Greg)
---
tools/virtiofsd/fuse_i.h | 1 +
tools/virtiofsd/fuse_lowlevel.c | 8 +++++++-
tools/virtiofsd/fuse_virtio.c | 27 +++++++++++++--------------
3 files changed, 21 insertions(+), 15 deletions(-)
Index: rhvgoyal-qemu/tools/virtiofsd/fuse_virtio.c
===================================================================
--- rhvgoyal-qemu.orig/tools/virtiofsd/fuse_virtio.c 2021-05-04 09:55:30.467514740 -0400
+++ rhvgoyal-qemu/tools/virtiofsd/fuse_virtio.c 2021-05-04 10:06:32.453801299 -0400
@@ -445,7 +445,6 @@ err:
static __thread bool clone_fs_called;
-/* Process one FVRequest in a thread pool */
static void fv_queue_worker(gpointer data, gpointer user_data)
{
struct fv_QueueInfo *qi = user_data;
@@ -604,11 +603,12 @@ static void *fv_queue_thread(void *opaqu
struct VuVirtq *q = vu_get_queue(dev, qi->qidx);
struct fuse_session *se = qi->virtio_dev->se;
GThreadPool *pool = NULL;
- GList *req_list = NULL;
+ GQueue req_queue = G_QUEUE_INIT;
if (se->thread_pool_size) {
- fuse_log(FUSE_LOG_DEBUG, "%s: Creating thread pool for Queue %d\n",
- __func__, qi->qidx);
+ fuse_log(FUSE_LOG_DEBUG, "%s: Creating thread pool for Queue %d."
+ " thread_pool_threshold=%u\n", __func__, qi->qidx,
+ se->thread_pool_threshold);
pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size,
FALSE, NULL);
if (!pool) {
@@ -686,22 +686,21 @@ static void *fv_queue_thread(void *opaqu
}
req->reply_sent = false;
-
- if (!se->thread_pool_size) {
- req_list = g_list_prepend(req_list, req);
- } else {
- g_thread_pool_push(pool, req, NULL);
- }
+ g_queue_push_tail(&req_queue, req);
}
pthread_mutex_unlock(&qi->vq_lock);
vu_dispatch_unlock(qi->virtio_dev);
/* Process all the requests. */
- if (!se->thread_pool_size && req_list != NULL) {
- g_list_foreach(req_list, fv_queue_worker, qi);
- g_list_free(req_list);
- req_list = NULL;
+ for (int i = g_queue_get_length(&req_queue); i > 0; i--) {
+ FVRequest *req = g_queue_pop_head(&req_queue);
+
+ if (se->thread_pool_size && i > se->thread_pool_threshold) {
+ g_thread_pool_push(pool, req, NULL);
+ } else {
+ fv_queue_worker(req, qi);
+ }
}
}
Index: rhvgoyal-qemu/tools/virtiofsd/fuse_i.h
===================================================================
--- rhvgoyal-qemu.orig/tools/virtiofsd/fuse_i.h 2021-05-04 09:55:30.467514740 -0400
+++ rhvgoyal-qemu/tools/virtiofsd/fuse_i.h 2021-05-04 10:04:58.737938382 -0400
@@ -73,6 +73,7 @@ struct fuse_session {
int vu_socketfd;
struct fv_VuDev *virtio_dev;
int thread_pool_size;
+ unsigned thread_pool_threshold;
};
struct fuse_chan {
Index: rhvgoyal-qemu/tools/virtiofsd/fuse_lowlevel.c
===================================================================
--- rhvgoyal-qemu.orig/tools/virtiofsd/fuse_lowlevel.c 2021-05-04 09:55:30.467514740 -0400
+++ rhvgoyal-qemu/tools/virtiofsd/fuse_lowlevel.c 2021-05-04 10:17:27.674809167 -0400
@@ -2432,6 +2432,7 @@ static const struct fuse_opt fuse_ll_opt
LL_OPTION("--socket-group=%s", vu_socket_group, 0),
LL_OPTION("--fd=%d", vu_listen_fd, 0),
LL_OPTION("--thread-pool-size=%d", thread_pool_size, 0),
+ LL_OPTION("--thread-pool-threshold=%u", thread_pool_threshold, 0),
FUSE_OPT_END
};
@@ -2452,7 +2453,11 @@ void fuse_lowlevel_help(void)
" --socket-path=PATH path for the vhost-user socket\n"
" --socket-group=GRNAME name of group for the vhost-user socket\n"
" --fd=FDNUM fd number of vhost-user socket\n"
- " --thread-pool-size=NUM thread pool size limit (default %d)\n",
+ " --thread-pool-size=NUM thread pool size limit (default %d)\n"
+ " --thread-pool-threshold=NUM\n"
+ " number of request threshold to\n"
+ " switch between inline and thread pool\n"
+ " processing of request\n",
THREAD_POOL_SIZE);
}
@@ -2508,6 +2513,7 @@ struct fuse_session *fuse_session_new(st
se->fd = -1;
se->vu_listen_fd = -1;
se->thread_pool_size = THREAD_POOL_SIZE;
+ se->thread_pool_threshold = 0;
se->conn.max_write = UINT_MAX;
se->conn.max_readahead = UINT_MAX;
More information about the Virtio-fs
mailing list