util/event-loop-base: Introduce options to set the thread pool size

The thread pool regulates itself: when idle, it kills threads until
empty, when in demand, it creates new threads until full. This behaviour
doesn't play well with latency sensitive workloads where the price of
creating a new thread is too high. For example, when paired with qemu's
'-mlock', or using safety features like SafeStack, creating a new thread
has been measured take multiple milliseconds.

In order to mitigate this let's introduce a new 'EventLoopBase'
property to set the thread pool size. The threads will be created during
the pool's initialization or upon updating the property's value, remain
available during its lifetime regardless of demand, and destroyed upon
freeing it. A properly characterized workload will then be able to
configure the pool to avoid any latency spikes.

Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Message-id: 20220425075723.20019-4-nsaenzju@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Nicolas Saenz Julienne 2022-04-25 09:57:23 +02:00 committed by Stefan Hajnoczi
parent 70ac26b9e5
commit 71ad4713cc
10 changed files with 133 additions and 5 deletions

View file

@ -14,6 +14,7 @@
#include "qemu/osdep.h"
#include "qom/object_interfaces.h"
#include "qapi/error.h"
#include "block/thread-pool.h"
#include "sysemu/event-loop-base.h"
typedef struct {
@ -21,9 +22,22 @@ typedef struct {
ptrdiff_t offset; /* field's byte offset in EventLoopBase struct */
} EventLoopBaseParamInfo;
static void event_loop_base_instance_init(Object *obj)
{
EventLoopBase *base = EVENT_LOOP_BASE(obj);
base->thread_pool_max = THREAD_POOL_MAX_THREADS_DEFAULT;
}
static EventLoopBaseParamInfo aio_max_batch_info = {
"aio-max-batch", offsetof(EventLoopBase, aio_max_batch),
};
static EventLoopBaseParamInfo thread_pool_min_info = {
"thread-pool-min", offsetof(EventLoopBase, thread_pool_min),
};
static EventLoopBaseParamInfo thread_pool_max_info = {
"thread-pool-max", offsetof(EventLoopBase, thread_pool_max),
};
static void event_loop_base_get_param(Object *obj, Visitor *v,
const char *name, void *opaque, Error **errp)
@ -95,12 +109,21 @@ static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
event_loop_base_get_param,
event_loop_base_set_param,
NULL, &aio_max_batch_info);
object_class_property_add(klass, "thread-pool-min", "int",
event_loop_base_get_param,
event_loop_base_set_param,
NULL, &thread_pool_min_info);
object_class_property_add(klass, "thread-pool-max", "int",
event_loop_base_get_param,
event_loop_base_set_param,
NULL, &thread_pool_max_info);
}
static const TypeInfo event_loop_base_info = {
.name = TYPE_EVENT_LOOP_BASE,
.parent = TYPE_OBJECT,
.instance_size = sizeof(EventLoopBase),
.instance_init = event_loop_base_instance_init,
.class_size = sizeof(EventLoopBaseClass),
.class_init = event_loop_base_class_init,
.abstract = true,