* [PATCH] qobject/json-writer: preallocate output buffer
@ 2026-05-29 2:34 Bin Guo
2026-05-29 6:13 ` Philippe Mathieu-Daudé
2026-06-02 8:34 ` Markus Armbruster
0 siblings, 2 replies; 5+ messages in thread
From: Bin Guo @ 2026-05-29 2:34 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru
json_writer_new() creates the output GString with g_string_new(NULL),
which starts at the GLib default of 64 bytes. Serializing typical
QMP responses then requires multiple reallocations as the buffer
grows -- for query-qmp-schema the GString is reallocated 12+ times.
Preallocate JSON_WRITER_INITIAL_SIZE (4096) bytes. This covers
most QMP responses without any reallocation. 4096 is one page on
most systems, which is efficient for the allocator. The JSONWriter
is a short-lived object so the preallocation does not accumulate.
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
---
qobject/json-writer.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/qobject/json-writer.c b/qobject/json-writer.c
index aac2c6ab71..fb3f3f3e3c 100644
--- a/qobject/json-writer.c
+++ b/qobject/json-writer.c
@@ -24,13 +24,16 @@ struct JSONWriter {
GByteArray *container_is_array;
};
+/* Covers most QMP responses without reallocation (one page) */
+#define JSON_WRITER_INITIAL_SIZE 4096
+
JSONWriter *json_writer_new(bool pretty)
{
JSONWriter *writer = g_new(JSONWriter, 1);
writer->pretty = pretty;
writer->need_comma = false;
- writer->contents = g_string_new(NULL);
+ writer->contents = g_string_sized_new(JSON_WRITER_INITIAL_SIZE);
writer->container_is_array = g_byte_array_new();
return writer;
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] qobject/json-writer: preallocate output buffer
2026-05-29 2:34 [PATCH] qobject/json-writer: preallocate output buffer Bin Guo
@ 2026-05-29 6:13 ` Philippe Mathieu-Daudé
2026-06-02 8:34 ` Markus Armbruster
1 sibling, 0 replies; 5+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-29 6:13 UTC (permalink / raw)
To: Bin Guo, qemu-devel; +Cc: armbru
On 29/5/26 04:34, Bin Guo wrote:
> json_writer_new() creates the output GString with g_string_new(NULL),
> which starts at the GLib default of 64 bytes. Serializing typical
> QMP responses then requires multiple reallocations as the buffer
> grows -- for query-qmp-schema the GString is reallocated 12+ times.
>
> Preallocate JSON_WRITER_INITIAL_SIZE (4096) bytes. This covers
> most QMP responses without any reallocation. 4096 is one page on
> most systems, which is efficient for the allocator.
Why not use qemu_real_host_page_size()?
Anyhow,
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> The JSONWriter
> is a short-lived object so the preallocation does not accumulate.
>
> Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
> ---
> qobject/json-writer.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/qobject/json-writer.c b/qobject/json-writer.c
> index aac2c6ab71..fb3f3f3e3c 100644
> --- a/qobject/json-writer.c
> +++ b/qobject/json-writer.c
> @@ -24,13 +24,16 @@ struct JSONWriter {
> GByteArray *container_is_array;
> };
>
> +/* Covers most QMP responses without reallocation (one page) */
> +#define JSON_WRITER_INITIAL_SIZE 4096
> +
> JSONWriter *json_writer_new(bool pretty)
> {
> JSONWriter *writer = g_new(JSONWriter, 1);
>
> writer->pretty = pretty;
> writer->need_comma = false;
> - writer->contents = g_string_new(NULL);
> + writer->contents = g_string_sized_new(JSON_WRITER_INITIAL_SIZE);
> writer->container_is_array = g_byte_array_new();
> return writer;
> }
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] qobject/json-writer: preallocate output buffer
2026-05-29 2:34 [PATCH] qobject/json-writer: preallocate output buffer Bin Guo
2026-05-29 6:13 ` Philippe Mathieu-Daudé
@ 2026-06-02 8:34 ` Markus Armbruster
2026-06-03 9:52 ` Daniel P. Berrangé
1 sibling, 1 reply; 5+ messages in thread
From: Markus Armbruster @ 2026-06-02 8:34 UTC (permalink / raw)
To: Bin Guo; +Cc: qemu-devel
Bin Guo <guobin@linux.alibaba.com> writes:
> json_writer_new() creates the output GString with g_string_new(NULL),
> which starts at the GLib default of 64 bytes. Serializing typical
> QMP responses then requires multiple reallocations as the buffer
> grows -- for query-qmp-schema the GString is reallocated 12+ times.
That's an extreme case. Most responses are *much* smaller. Still,
starting with a larger buffer makes sense.
> Preallocate JSON_WRITER_INITIAL_SIZE (4096) bytes. This covers
> most QMP responses without any reallocation. 4096 is one page on
> most systems, which is efficient for the allocator.
I doubt "one page" matters. How many QMP commands get executed in
practice? A couple of hundred during startup, then tens per second?
Probably less than that.
> The JSONWriter
> is a short-lived object so the preallocation does not accumulate.
>
> Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
> ---
> qobject/json-writer.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/qobject/json-writer.c b/qobject/json-writer.c
> index aac2c6ab71..fb3f3f3e3c 100644
> --- a/qobject/json-writer.c
> +++ b/qobject/json-writer.c
> @@ -24,13 +24,16 @@ struct JSONWriter {
> GByteArray *container_is_array;
> };
>
> +/* Covers most QMP responses without reallocation (one page) */
Covering most responses matters, one page does not. Suggest
/* Should cover most QMP responses without reallocation */
> +#define JSON_WRITER_INITIAL_SIZE 4096
> +
> JSONWriter *json_writer_new(bool pretty)
> {
> JSONWriter *writer = g_new(JSONWriter, 1);
>
> writer->pretty = pretty;
> writer->need_comma = false;
> - writer->contents = g_string_new(NULL);
> + writer->contents = g_string_sized_new(JSON_WRITER_INITIAL_SIZE);
> writer->container_is_array = g_byte_array_new();
> return writer;
> }
Consider tweaking the commit message and the comment to address my
remarks.
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] qobject/json-writer: preallocate output buffer
2026-06-02 8:34 ` Markus Armbruster
@ 2026-06-03 9:52 ` Daniel P. Berrangé
2026-06-03 10:24 ` Markus Armbruster
0 siblings, 1 reply; 5+ messages in thread
From: Daniel P. Berrangé @ 2026-06-03 9:52 UTC (permalink / raw)
To: Markus Armbruster; +Cc: Bin Guo, qemu-devel
On Tue, Jun 02, 2026 at 10:34:43AM +0200, Markus Armbruster wrote:
> Bin Guo <guobin@linux.alibaba.com> writes:
>
> > json_writer_new() creates the output GString with g_string_new(NULL),
> > which starts at the GLib default of 64 bytes. Serializing typical
> > QMP responses then requires multiple reallocations as the buffer
> > grows -- for query-qmp-schema the GString is reallocated 12+ times.
>
> That's an extreme case. Most responses are *much* smaller. Still,
> starting with a larger buffer makes sense.
>
> > Preallocate JSON_WRITER_INITIAL_SIZE (4096) bytes. This covers
> > most QMP responses without any reallocation. 4096 is one page on
> > most systems, which is efficient for the allocator.
>
> I doubt "one page" matters. How many QMP commands get executed in
> practice? A couple of hundred during startup, then tens per second?
> Probably less than that.
NB tens per second, repeated across possibly 100's or even 1000's of
VMs on the single host though.
If we want an arbitrary moderately size buffer, one page feels like
a reasonable place to aim for
>
> > The JSONWriter
> > is a short-lived object so the preallocation does not accumulate.
> >
> > Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
> > ---
> > qobject/json-writer.c | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/qobject/json-writer.c b/qobject/json-writer.c
> > index aac2c6ab71..fb3f3f3e3c 100644
> > --- a/qobject/json-writer.c
> > +++ b/qobject/json-writer.c
> > @@ -24,13 +24,16 @@ struct JSONWriter {
> > GByteArray *container_is_array;
> > };
> >
> > +/* Covers most QMP responses without reallocation (one page) */
>
> Covering most responses matters, one page does not. Suggest
>
> /* Should cover most QMP responses without reallocation */
>
> > +#define JSON_WRITER_INITIAL_SIZE 4096
> > +
> > JSONWriter *json_writer_new(bool pretty)
> > {
> > JSONWriter *writer = g_new(JSONWriter, 1);
> >
> > writer->pretty = pretty;
> > writer->need_comma = false;
> > - writer->contents = g_string_new(NULL);
> > + writer->contents = g_string_sized_new(JSON_WRITER_INITIAL_SIZE);
> > writer->container_is_array = g_byte_array_new();
> > return writer;
> > }
>
> Consider tweaking the commit message and the comment to address my
> remarks.
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
>
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] qobject/json-writer: preallocate output buffer
2026-06-03 9:52 ` Daniel P. Berrangé
@ 2026-06-03 10:24 ` Markus Armbruster
0 siblings, 0 replies; 5+ messages in thread
From: Markus Armbruster @ 2026-06-03 10:24 UTC (permalink / raw)
To: Daniel P. Berrangé; +Cc: Bin Guo, qemu-devel
Daniel P. Berrangé <berrange@redhat.com> writes:
> On Tue, Jun 02, 2026 at 10:34:43AM +0200, Markus Armbruster wrote:
>> Bin Guo <guobin@linux.alibaba.com> writes:
>>
>> > json_writer_new() creates the output GString with g_string_new(NULL),
>> > which starts at the GLib default of 64 bytes. Serializing typical
>> > QMP responses then requires multiple reallocations as the buffer
>> > grows -- for query-qmp-schema the GString is reallocated 12+ times.
>>
>> That's an extreme case. Most responses are *much* smaller. Still,
>> starting with a larger buffer makes sense.
>>
>> > Preallocate JSON_WRITER_INITIAL_SIZE (4096) bytes. This covers
>> > most QMP responses without any reallocation. 4096 is one page on
>> > most systems, which is efficient for the allocator.
>>
>> I doubt "one page" matters. How many QMP commands get executed in
>> practice? A couple of hundred during startup, then tens per second?
>> Probably less than that.
>
> NB tens per second, repeated across possibly 100's or even 1000's of
> VMs on the single host though.
>
> If we want an arbitrary moderately size buffer, one page feels like
> a reasonable place to aim for
I think 4KiB is a reasonable initial size regardless of the host's page
size. That was my argument.
If we care, we can instrument QEMU to gather response size statistics.
[...]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-03 10:25 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-29 2:34 [PATCH] qobject/json-writer: preallocate output buffer Bin Guo
2026-05-29 6:13 ` Philippe Mathieu-Daudé
2026-06-02 8:34 ` Markus Armbruster
2026-06-03 9:52 ` Daniel P. Berrangé
2026-06-03 10:24 ` Markus Armbruster
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.