From: Eric Blake <eblake@redhat.com>
To: Orit Wasserman <owasserm@redhat.com>
Cc: peter.maydell@linaro.org, aliguori@us.ibm.com,
quintela@redhat.com, stefanha@gmail.com, qemu-devel@nongnu.org,
mdroth@linux.vnet.ibm.com, blauwirbel@gmail.com,
Petter Svard <petters@cs.umu.se>,
Benoit Hudzia <benoit.hudzia@sap.com>,
avi@redhat.com, Aidan Shribman <aidan.shribman@sap.com>,
pbonzini@redhat.com, chegu_vinod@hp.com
Subject: Re: [Qemu-devel] [PATCH v12 10/13] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions
Date: Tue, 19 Jun 2012 12:08:27 -0600 [thread overview]
Message-ID: <4FE0C01B.1020000@redhat.com> (raw)
In-Reply-To: <1340120601-24747-11-git-send-email-owasserm@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 3943 bytes --]
On 06/19/2012 09:43 AM, Orit Wasserman wrote:
> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
> Signed-off-by: Petter Svard <petters@cs.umu.se>
> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> ---
> savevm.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 91 insertions(+), 0 deletions(-)
>
> +int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
> + uint8_t *dst, int dlen)
> +{
> + uint32_t zrun_len = 0, nzrun_len = 0;
> + int d = 0 , i = 0;
> + uint8_t *nzrun_start = NULL;
> +
> + while (i < slen) {
> + /* overflow */
> + if (d + 2 > dlen) {
> + return -1;
> + }
> +
> + while (!(old_buf[i] ^ new_buf[i]) && ++i <= slen) {
> + zrun_len++;
> + }
Can we vectorize this to compare a word at a time for improved speed?
It would be really cool if glibc had an interface like memcmp(), but
which returned the offset of the first difference instead of a
comparison of the overall memory regions. But even without such an
interface, pseudocode such as:
while (i < slen) {
check for overflow
if (not aligned)
up to sizeof(long) byte comparisons
while (long comparisons && not end)
increment i by sizeof(long)
if (end of buffer) {
either buffer unchanged, or we have trailing zrun
break;
}
// found a word that differed
do byte-wise comparisons on that word
then back to word-size xor, checking for no zero bytes in the xor (or
anywhere that a zero byte occurs in isolation, it is more compact to
pass that lone byte as part of the xor encoding instead of breaking out
to a zrun)
}
> +
> + zrun_len = 0;
> + nzrun_start = new_buf + i;
> + while ((old_buf[i] ^ new_buf[i]) != 0 && ++i <= slen) {
> + nzrun_len++;
> + }
Note that the encoding for a single unchanged byte with bytes changed on
both sides is more compact to pass the unchanged byte as part of the
nzrun, instead of breaking out into a zrun and starting a second nzrun.
If I'm analyzing things correctly, that's also true for a run of two
bytes, and it's not until we get to a run of three or more unchanged
bytes where we start to get compression (except for the corner case of
ending on a 1- or 2-byte zrun). Should we be altering this algorithm to
take advantage of this?
> +int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen)
> +{
> + int i = 0, d = 0;
> + uint32_t count = 0;
> +
> + while (i < slen) {
> +
> + /* zrun */
> + i += uleb128_decode_small(src + i, &count);
> + d += count;
> +
> + /* overflow */
> + g_assert(d <= dlen);
Again, is g_assert() appropriate for parsing user-supplied input, or are
there more appropriate ways for gracefully failing an incoming migration
attempt from corrupt data?
> +
> + /* completed decoding */
> + if (i == slen - 1) {
> + return d;
> + }
> +
> + /* nzrun */
> + i += uleb128_decode_small(src + i, &count);
> +
> + g_assert(d + count <= dlen);
> +
> + memcpy(dst + d , src + i, count);
Am I correct that you are using XOR to compute the locations of nzrun,
but then transferring the original data (and not the xor data) over the
wire? This was not made clear in the doc patch of 3/13. I would
suggest adding an example to the docs of a 4k page that consists only of
a short string at the beginning of the page (and NUL bytes thereafter),
then show both the before and after version of that page to demonstrate
sparse memory changes, as well as the XBZRLE encoding of that page.
--
Eric Blake eblake@redhat.com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 620 bytes --]
next prev parent reply other threads:[~2012-06-19 18:08 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-19 15:43 [Qemu-devel] [PATCH v12 00/13] XBZRLE delta for live migration of large memory app Orit Wasserman
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 01/13] Add MigrationParams structure Orit Wasserman
2012-06-19 16:00 ` Eric Blake
2012-06-19 16:02 ` Orit Wasserman
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 02/13] Add migration capabilites Orit Wasserman
2012-06-19 16:27 ` Eric Blake
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 03/13] Add XBZRLE documentation Orit Wasserman
2012-06-19 16:46 ` Eric Blake
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 04/13] Add cache handling functions Orit Wasserman
2012-06-19 16:51 ` Eric Blake
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 05/13] Add uleb encoding/decoding functions Orit Wasserman
2012-06-19 16:59 ` Eric Blake
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 06/13] Add save_block_hdr function Orit Wasserman
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 07/13] Add debugging infrastructure Orit Wasserman
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 08/13] Change ram_save_block to return -1 if there are no more changes Orit Wasserman
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 09/13] Add migration_end function Orit Wasserman
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 10/13] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions Orit Wasserman
2012-06-19 18:08 ` Eric Blake [this message]
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 11/13] Add XBZRLE to ram_save_block and ram_save_live Orit Wasserman
2012-06-19 18:50 ` Eric Blake
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 12/13] Add set_cachesize command Orit Wasserman
2012-06-19 19:13 ` Eric Blake
2012-06-19 15:43 ` [Qemu-devel] [PATCH v12 13/13] Add XBZRLE statistics Orit Wasserman
2012-06-19 19:20 ` Eric Blake
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=4FE0C01B.1020000@redhat.com \
--to=eblake@redhat.com \
--cc=aidan.shribman@sap.com \
--cc=aliguori@us.ibm.com \
--cc=avi@redhat.com \
--cc=benoit.hudzia@sap.com \
--cc=blauwirbel@gmail.com \
--cc=chegu_vinod@hp.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=owasserm@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=petters@cs.umu.se \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
--cc=stefanha@gmail.com \
/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;
as well as URLs for NNTP newsgroup(s).