From: Markus Armbruster <armbru@redhat.com>
To: Jaehoon Kim <jhkim@linux.ibm.com>
Cc: qemu-devel@nongnu.org, qemu-block@nongnu.org,
mjrosato@linux.ibm.com, farman@linux.ibm.com,
pbonzini@redhat.com, stefanha@redhat.com, fam@euphon.net,
armbru@redhat.com, eblake@redhat.com, berrange@redhat.com,
eduardo@habkost.net, dave@treblig.org, sw@weilnetz.de
Subject: Re: [PATCH RFC v2 3/3] qapi/iothread: introduce poll-weight parameter for aio-poll
Date: Wed, 25 Mar 2026 15:04:10 +0100 [thread overview]
Message-ID: <87o6kckntx.fsf@pond.sub.org> (raw)
In-Reply-To: <20260323135451.579655-4-jhkim@linux.ibm.com> (Jaehoon Kim's message of "Mon, 23 Mar 2026 08:54:51 -0500")
Jaehoon Kim <jhkim@linux.ibm.com> writes:
> Introduce a configurable poll-weight parameter for adaptive polling
> in IOThread. This parameter replaces the hardcoded POLL_WEIGHT_SHIFT
> constant, allowing runtime control over how much the most recent
> event interval affects the next polling duration calculation.
>
> The poll-weight parameter uses a shift value where larger values
> decrease the weight of the current interval, enabling more gradual
> adjustments. When set to 0, a default value of 3 is used (meaning
> the current interval contributes approximately 1/8 to the weighted
> average).
>
> This patch also removes the hardcoded default values for poll-grow
> and poll-shrink parameters from the grow_polling_time() and
> shrink_polling_time() functions, as these defaults are now properly
> initialized in iothread.c during IOThread creation.
>
> Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com>
[...]
> diff --git a/qapi/misc.json b/qapi/misc.json
> index 28c641fe2f..39d17010bc 100644
> --- a/qapi/misc.json
> +++ b/qapi/misc.json
> @@ -85,6 +85,12 @@
Note: this is IOThreadInfo, used only as return value of
query-iothreads.
> # @poll-shrink: how many ns will be removed from polling time, 0 means
> # that it's not configured (since 2.9)
> #
> +# @poll-weight: the weight factor for adaptive polling.
> +# Determines how much the current event interval contributes to
> +# the next polling time calculation. Valid values are 1 or
> +# greater. 0 selects the system default value which is current 3
Does query-iothreads actually return 0? I'd expect it to return the
value that is actually used.
> +# (since 10.2)
11.1 most likely.
> +#
> # @aio-max-batch: maximum number of requests in a batch for the AIO
> # engine, 0 means that the engine will use its default (since 6.1)
> #
> @@ -96,6 +102,7 @@
> 'poll-max-ns': 'int',
> 'poll-grow': 'int',
> 'poll-shrink': 'int',
> + 'poll-weight': 'int',
> 'aio-max-batch': 'int' } }
>
> ##
> diff --git a/qapi/qom.json b/qapi/qom.json
> index c653248f85..feb80b6cfe 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -606,6 +606,11 @@
> # algorithm detects it is spending too long polling without
> # encountering events. 0 selects a default behaviour (default: 0)
> #
> +# @poll-weight: the weight factor for adaptive polling.
> +# Determines how much the current event interval contributes to
> +# the next polling time calculation. Valid values are 1 or
> +# greater. If set to 0, the default value of 3 is used.
The commit message hints what the valid values mean, the doc comment
doesn't even that. Do users need to know?
Code [*] below uses it like time >> poll_weight, where @time is int64_t.
poll_weight > 63 is undefined behavior, which is a no-no. Please reject
such values. poll_weight == 64 results in zero. Is that useful?
Missing: (default: 0) (since 11.1)
> +#
> # The @aio-max-batch option is available since 6.1.
> #
> # Since: 2.0
> @@ -614,7 +619,8 @@
> 'base': 'EventLoopBaseProperties',
> 'data': { '*poll-max-ns': 'int',
> '*poll-grow': 'int',
> - '*poll-shrink': 'int' } }
> + '*poll-shrink': 'int',
> + '*poll-weight': 'int' } }
>
> ##
> # @MainLoopProperties:
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 69e5a874c1..8ddf6c8d36 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -6413,7 +6413,7 @@ SRST
>
> CN=laptop.example.com,O=Example Home,L=London,ST=London,C=GB
>
> - ``-object iothread,id=id,poll-max-ns=poll-max-ns,poll-grow=poll-grow,poll-shrink=poll-shrink,aio-max-batch=aio-max-batch``
> + ``-object iothread,id=id,poll-max-ns=poll-max-ns,poll-grow=poll-grow,poll-shrink=poll-shrink,poll-weight=poll-weight,aio-max-batch=aio-max-batch``
> Creates a dedicated event loop thread that devices can be
> assigned to. This is known as an IOThread. By default device
> emulation happens in vCPU threads or the main event loop thread.
> @@ -6449,6 +6449,11 @@ SRST
> the polling time when the algorithm detects it is spending too
> long polling without encountering events.
>
> + The ``poll-weight`` parameter is the weight factor used in the
> + adaptive polling algorithm. It determines how much the most
> + recent event interval affects the calculation of the next
> + polling duration.
> +
> The ``aio-max-batch`` parameter is the maximum number of requests
> in a batch for the AIO engine, 0 means that the engine will use
> its default.
> diff --git a/tests/unit/test-nested-aio-poll.c b/tests/unit/test-nested-aio-poll.c
> index 9ab1ad08a7..4c38f36fd4 100644
> --- a/tests/unit/test-nested-aio-poll.c
> +++ b/tests/unit/test-nested-aio-poll.c
> @@ -81,7 +81,7 @@ static void test(void)
> qemu_set_current_aio_context(td.ctx);
>
> /* Enable polling */
> - aio_context_set_poll_params(td.ctx, 1000000, 2, 2, &error_abort);
> + aio_context_set_poll_params(td.ctx, 1000000, 2, 2, 3, &error_abort);
>
> /* Make the event notifier active (set) right away */
> event_notifier_init(&td.poll_notifier, 1);
> diff --git a/util/aio-posix.c b/util/aio-posix.c
> index 2b3522f2f9..13b7f94911 100644
> --- a/util/aio-posix.c
> +++ b/util/aio-posix.c
> @@ -29,7 +29,6 @@
>
> /* Stop userspace polling on a handler if it isn't active for some time */
> #define POLL_IDLE_INTERVAL_NS (7 * NANOSECONDS_PER_SECOND)
> -#define POLL_WEIGHT_SHIFT (3)
>
> static void adjust_block_ns(AioContext *ctx, int64_t block_ns);
> static void grow_polling_time(AioContext *ctx, int64_t block_ns);
> @@ -593,10 +592,6 @@ static void shrink_polling_time(AioContext *ctx, int64_t block_ns)
> int64_t old = ctx->poll_ns;
> int64_t shrink = ctx->poll_shrink;
>
> - if (shrink == 0) {
> - shrink = 2;
> - }
> -
> if (block_ns < (ctx->poll_ns / shrink)) {
> ctx->poll_ns /= shrink;
> }
> @@ -610,10 +605,6 @@ static void grow_polling_time(AioContext *ctx, int64_t block_ns)
> int64_t old = ctx->poll_ns;
> int64_t grow = ctx->poll_grow;
>
> - if (grow == 0) {
> - grow = 2;
> - }
> -
> if (block_ns > ctx->poll_ns * grow) {
> ctx->poll_ns = block_ns;
> } else {
> @@ -640,8 +631,8 @@ static void adjust_block_ns(AioContext *ctx, int64_t block_ns)
> * poll.ns to smooth out polling time adjustments.
> */
> node->poll.ns = node->poll.ns
> - ? (node->poll.ns - (node->poll.ns >> POLL_WEIGHT_SHIFT))
> - + (block_ns >> POLL_WEIGHT_SHIFT) : block_ns;
> + ? (node->poll.ns - (node->poll.ns >> ctx->poll_weight))
> + + (block_ns >> ctx->poll_weight) : block_ns;
[*] This is the use of @poll-weight referred to above.
>
> if (node->poll.ns > ctx->poll_max_ns) {
> node->poll.ns = 0;
> @@ -831,7 +822,8 @@ void aio_context_destroy(AioContext *ctx)
> }
>
> void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
> - int64_t grow, int64_t shrink, Error **errp)
> + int64_t grow, int64_t shrink,
> + int64_t weight, Error **errp)
> {
> AioHandler *node;
>
> @@ -848,6 +840,7 @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
> ctx->poll_max_ns = max_ns;
> ctx->poll_grow = grow;
> ctx->poll_shrink = shrink;
> + ctx->poll_weight = weight;
> ctx->poll_ns = 0;
>
> aio_notify(ctx);
[...]
next prev parent reply other threads:[~2026-03-25 14:05 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-23 13:54 [PATCH RFC v2 0/3] improve aio-polling efficiency Jaehoon Kim
2026-03-23 13:54 ` [PATCH RFC v2 1/3] aio-poll: avoid unnecessary polling time computation Jaehoon Kim
2026-03-25 17:22 ` Stefan Hajnoczi
2026-03-23 13:54 ` [PATCH RFC v2 2/3] aio-poll: refine iothread polling using weighted handler intervals Jaehoon Kim
2026-03-25 20:37 ` Stefan Hajnoczi
2026-03-23 13:54 ` [PATCH RFC v2 3/3] qapi/iothread: introduce poll-weight parameter for aio-poll Jaehoon Kim
2026-03-25 14:04 ` Markus Armbruster [this message]
2026-03-25 16:52 ` Stefan Hajnoczi
2026-03-25 16:56 ` Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87o6kckntx.fsf@pond.sub.org \
--to=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=dave@treblig.org \
--cc=eblake@redhat.com \
--cc=eduardo@habkost.net \
--cc=fam@euphon.net \
--cc=farman@linux.ibm.com \
--cc=jhkim@linux.ibm.com \
--cc=mjrosato@linux.ibm.com \
--cc=pbonzini@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=sw@weilnetz.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox