qtest: hex nib buffering
cover qtest: hex nib buffering
This patch requires (as context only) patches 1,2 (but excluding patch 4) from:
Message-id: [email protected] [PATCH v3 0/5] qtest: base64 r/w and faster memset
Or, alternatively, use the github mirrors below.
==
For convenience, this branch is available at:
https://github.com/jnsnow/qemu.git branch qtest_batching
https://github.com/jnsnow/qemu/tree/qtest_batching
This version is tagged qtest_batching-v1:
https://github.com/jnsnow/qemu/releases/tag/qtest_batching-v1
==
John Snow (1):
qtest: pre-buffer hex nibs
qtest.c | 11 +++++++---- tests/libqtest.c | 8 +++++--- 2 files changed, 12 insertions(+), 7 deletions(-)
Signature · 1 line
2.1.0
PATCH 1/1 qtest: pre-buffer hex nibs
Instead of converting each byte one-at-a-time and then sending each byte over the wire, use sprintf() to pre-compute all of the hex nibs into a single buffer, then send the entire buffer all at once.
This gives a moderate speed boost to memread() and memwrite() functions.
--- qtest.c | 11 +++++++---- tests/libqtest.c | 8 +++++--- 2 files changed, 12 insertions(+), 7 deletions(-)
qtest.c +7 -4
@@ -414,6 +414,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) }else if (strcmp (words[0 ],"read" ) ==0 ) {uint64_t addr, len, i;uint8_t *data; +char *enc;g_assert (words[1 ] && words[2 ]); addr =strtoull (words[1 ],NULL ,0 );
@@ -422,14 +423,16 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) data =g_malloc (len);cpu_physical_memory_read (addr, data, len); -qtest_send_prefix (chr); -qtest_send (chr,"OK 0x" ); + enc =g_malloc (2 * len +1 );for (i =0 ; i < len; i++) { -qtest_sendf (chr,"%02x" , data[i]); +sprintf (&enc[i *2 ],"%02x" , data[i]); } -qtest_send (chr,"\n" ); + +qtest_send_prefix (chr); +qtest_sendf (chr,"OK 0x%s\n" , enc);g_free (data); +g_free (enc); }else if (strcmp (words[0 ],"b64read" ) ==0 ) {uint64_t addr, len;uint8_t *data;
tests/libqtest.c +5 -3
@@ -730,13 +730,15 @@ void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size) {const uint8_t *ptr = data;size_t i; +char *enc =g_malloc (2 * size +1 ); -qtest_sendf (s,"write 0x%" PRIx64" 0x%zx 0x" , addr, size);for (i =0 ; i < size; i++) { -qtest_sendf (s,"%02x" , ptr[i]); +sprintf (&enc[i *2 ],"%02x" , ptr[i]); } -qtest_sendf (s,"\n" ); + +qtest_sendf (s,"write 0x%" PRIx64" 0x%zx 0x%s\n" , addr, size, enc);qtest_rsp (s,0 ); +g_free (enc); }void qtest_memset (QTestState *s,uint64_t addr,uint8_t pattern,size_t size)
Signature · 1 line
2.1.0
Re: [Qemu-devel] [PATCH 1/1] qtest: pre-buffer hex nibs
Quoted 9 lines · John Snow
Instead of converting each byte one-at-a-time and then sending each byte over the wire, use
sprintf()to pre-compute all of the hex nibs into a single buffer, then send the entire buffer all at once.This gives a moderate speed boost to
memread()andmemwrite()functions.Signed-off-by John Snow <[email protected]>---
qtest.c static void qtest_process_command(CharDriverState *chr, gchar **words) · line 428
Quoted 6 lines
qtest.c +2
-3-qtest_send_prefix (chr); -qtest_send (chr,"OK 0x" ); + enc =g_malloc (2 * len +1 );for (i =0 ; i < len; i++) { -qtest_sendf (chr,"%02x" , data[i]); +sprintf (&enc[i *2 ],"%02x" , data[i]);
Making a function call to sprintf() has a lot of overhead. Isn't it even faster to open-code the conversion, something like:
for (i = 0; i < len; i++) {
const char digits[] = "0123456789abcdef";
enc[i * 2] = digits[data[i] >> 4];
enc[i * 2 + 1] = digits[data[i] & 0xf];
}enc[len * 2] = '\0';
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH 1/1] qtest: pre-buffer hex nibs
Quoted 11 lines · Eric Blake
Quoted 9 lines · John Snow
Instead of converting each byte one-at-a-time and then sending each byte over the wire, use
sprintf()to pre-compute all of the hex nibs into a single buffer, then send the entire buffer all at once.This gives a moderate speed boost to
memread()andmemwrite()functions.Signed-off-by John Snow <[email protected]> ---
Quoted 8 lines
Quoted 4 lines
-
qtest_send_prefix(chr); - qtest_send(chr, "OK
0x"); + enc =g_malloc(2 * len + 1); for (i = 0; i < len;
i++) { -qtest_sendf(chr, "%02x", data[i]); +sprintf(&enc[i * 2], "%02x", data[i]);Making a function call to
sprintf()has a lot of overhead. Isn't it even faster to open-code the conversion, something like:
"Maybe."
Quoted 4 lines
for (i = 0; i < len; i++) { const char digits[] = "
0123456789abcdef"; enc[i * 2] = digits[data[i] >> 4]; enc[i * 2 + 1] = digits[data[i] &0xf]; } enc[len * 2] = '\0';
In practice I didn't see a statistical difference between my previous nib-encoding function on my machine and this sprintf version, so I opted not to add any new bit twiddling.
The bulk of the savings comes from not engaging the full socket send for two bytes over and over and over again.
--js
Re: [Qemu-devel] [PATCH 1/1] qtest: pre-buffer hex nibs
In reply to John SnowQuoted 7 lines · John Snow
Instead of converting each byte one-at-a-time and then sending each byte over the wire, use
sprintf()to pre-compute all of the hex nibs into a single buffer, then send the entire buffer all at once.This gives a moderate speed boost to
memread()andmemwrite()functions.Signed-off-by John Snow <[email protected]>