* [Qemu-devel] [PATCH v2] iov: avoid memcpy for "simple" iov_from_buf/iov_to_buf
@ 2015-12-22 11:03 Paolo Bonzini
2015-12-23 4:45 ` Stefan Hajnoczi
0 siblings, 1 reply; 2+ messages in thread
From: Paolo Bonzini @ 2015-12-22 11:03 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha
memcpy can take a large amount of time for small reads and writes.
For virtio it is a common case that the first iovec can satisfy the
whole read or write. In that case, and if bytes is a constant to
avoid excessive growth of code, inline the first iteration
into the caller.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
v1->v2: check for overflow in offset + bytes, which
is covered by test-iov
include/qemu/iov.h | 34 ++++++++++++++++++++++++++++++----
util/iov.c | 8 ++++----
2 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
index 569b2c2..2847551 100644
--- a/include/qemu/iov.h
+++ b/include/qemu/iov.h
@@ -39,10 +39,36 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);
* such "large" value is -1 (sinice size_t is unsigned),
* so specifying `-1' as `bytes' means 'up to the end of iovec'.
*/
-size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
- size_t offset, const void *buf, size_t bytes);
-size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
- size_t offset, void *buf, size_t bytes);
+size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
+ size_t offset, const void *buf, size_t bytes);
+size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt,
+ size_t offset, void *buf, size_t bytes);
+
+static inline size_t
+iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
+ size_t offset, const void *buf, size_t bytes)
+{
+ if (__builtin_constant_p(bytes) && iov_cnt &&
+ offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
+ memcpy(iov[0].iov_base + offset, buf, bytes);
+ return bytes;
+ } else {
+ return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes);
+ }
+}
+
+static inline size_t
+iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
+ size_t offset, void *buf, size_t bytes)
+{
+ if (__builtin_constant_p(bytes) && iov_cnt &&
+ offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
+ memcpy(buf, iov[0].iov_base + offset, bytes);
+ return bytes;
+ } else {
+ return iov_to_buf_full(iov, iov_cnt, offset, buf, bytes);
+ }
+}
/**
* Set data bytes pointed out by iovec `iov' of size `iov_cnt' elements,
diff --git a/util/iov.c b/util/iov.c
index a0d5934..f113467 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -19,8 +19,8 @@
#include "qemu/iov.h"
#include "qemu/sockets.h"
-size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
- size_t offset, const void *buf, size_t bytes)
+size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
+ size_t offset, const void *buf, size_t bytes)
{
size_t done;
unsigned int i;
@@ -38,8 +38,8 @@ size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
return done;
}
-size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
- size_t offset, void *buf, size_t bytes)
+size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt,
+ size_t offset, void *buf, size_t bytes)
{
size_t done;
unsigned int i;
--
2.5.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [Qemu-devel] [PATCH v2] iov: avoid memcpy for "simple" iov_from_buf/iov_to_buf
2015-12-22 11:03 [Qemu-devel] [PATCH v2] iov: avoid memcpy for "simple" iov_from_buf/iov_to_buf Paolo Bonzini
@ 2015-12-23 4:45 ` Stefan Hajnoczi
0 siblings, 0 replies; 2+ messages in thread
From: Stefan Hajnoczi @ 2015-12-23 4:45 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, stefanha
[-- Attachment #1: Type: text/plain, Size: 771 bytes --]
On Tue, Dec 22, 2015 at 12:03:33PM +0100, Paolo Bonzini wrote:
> memcpy can take a large amount of time for small reads and writes.
> For virtio it is a common case that the first iovec can satisfy the
> whole read or write. In that case, and if bytes is a constant to
> avoid excessive growth of code, inline the first iteration
> into the caller.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> v1->v2: check for overflow in offset + bytes, which
> is covered by test-iov
>
> include/qemu/iov.h | 34 ++++++++++++++++++++++++++++++----
> util/iov.c | 8 ++++----
> 2 files changed, 34 insertions(+), 8 deletions(-)
Thanks, applied to my block tree:
https://github.com/stefanha/qemu/commits/block
Stefan
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-12-23 4:46 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-22 11:03 [Qemu-devel] [PATCH v2] iov: avoid memcpy for "simple" iov_from_buf/iov_to_buf Paolo Bonzini
2015-12-23 4:45 ` Stefan Hajnoczi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).