From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41063) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZjpJv-0004Qj-RX for qemu-devel@nongnu.org; Wed, 07 Oct 2015 10:03:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZjpJp-00050m-OR for qemu-devel@nongnu.org; Wed, 07 Oct 2015 10:03:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53775) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZjpJp-00050e-HU for qemu-devel@nongnu.org; Wed, 07 Oct 2015 10:03:45 -0400 Date: Wed, 7 Oct 2015 15:03:41 +0100 From: "Dr. David Alan Gilbert" Message-ID: <20151007140340.GG2710@work-vm> References: <5614531B.5080107@redhat.com> <1444198846-5383-1-git-send-email-den@openvz.org> <1444198846-5383-7-git-send-email-den@openvz.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <1444198846-5383-7-git-send-email-den@openvz.org> Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH 6/8] migration: implementation of hook_ram_sync List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Denis V. Lunev" Cc: Igor Redko , jsnow@redhat.com, qemu-devel@nongnu.org, annam@virtuozzo.com * Denis V. Lunev (den@openvz.org) wrote: > From: Igor Redko >=20 > The key feature of the test transport is receiving information > about dirty memory. The qemu_test_sync_hook() allows to use > the migration infrastructure(code) for this purpose. >=20 > All calls of this hook will be from ram_save_pending(). >=20 > At the first call of this hook we need to save the initial > size of VM memory and put the migration thread to sleep for > decent period (downtime for example). During this period > guest would dirty memory. >=20 > The second and the last call. > We make our estimation of dirty bytes rate assuming that time > between two synchronizations of dirty bitmap differs from downtime > negligibly. >=20 > An alternative to this approach is receiving information about > size of data =E2=80=9Ctransmitted=E2=80=9D through the transport. Howev= er, this > way creates large time and memory overheads: > 1/Transmitted guest=E2=80=99s memory pages are copied to QEMUFile=E2=80= =99s buffer > (~8 sec per 4GB VM) > 2/Dirty memory pages are processed one by one (~60msec per 4GB VM) That's not true for two reasons: 1) As long as you register a writev_buffer method on the QEMUFile RAM Pages get added by using add_to_iovec rather than actually copying the data; so all the other stuff does go that way (as do the page headers) 2) If you make it look like the rdma transport and register the 'save_= page' hook I think the overhead is even smaller. Dave >=20 > Signed-off-by: Igor Redko > Reviewed-by: Anna Melekhova > Signed-off-by: Denis V. Lunev > --- > migration/migration.c | 8 ++++++++ > migration/test.c | 36 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 44 insertions(+) >=20 > diff --git a/migration/migration.c b/migration/migration.c > index d6cb3e2..3182e15 100644 > --- a/migration/migration.c > +++ b/migration/migration.c > @@ -1058,6 +1058,14 @@ static void *migration_thread(void *opaque) > MIGRATION_STATUS_FAILED); > break; > } > + > + if (migrate_is_test()) { > + /* since no data is transfered during estimation all > + all measurements below will be incorrect. > + as well no need for delays. */ > + continue; > + } > + > current_time =3D qemu_clock_get_ms(QEMU_CLOCK_REALTIME); > if (current_time >=3D initial_time + BUFFER_DELAY) { > uint64_t transferred_bytes =3D qemu_ftell(s->file) - initi= al_bytes; > diff --git a/migration/test.c b/migration/test.c > index 8d06988..b4d0761 100644 > --- a/migration/test.c > +++ b/migration/test.c > @@ -18,6 +18,7 @@ typedef struct QEMUFileTest { > =20 > static uint64_t transfered_bytes; > static uint64_t initial_bytes; > +static int sync_cnt; > =20 > static ssize_t qemu_test_put_buffer(void *opaque, const uint8_t *buf, > int64_t pos, size_t size) > @@ -31,7 +32,41 @@ static int qemu_test_close(void *opaque) > return 0; > } > =20 > +static int qemu_test_sync_hook(QEMUFile *f, void *opaque, > + uint64_t flags, void *data) > +{ > + static uint64_t dirtied_bytes; > + static uint64_t sleeptime_mcs; > + int64_t time_delta; > + uint64_t remaining_bytes =3D *((uint64_t *) data); > + MigrationState *s =3D (MigrationState *) opaque; > + switch (sync_cnt++) { > + case 0: > + /* First call will be from ram_save_begin > + * so we need to save initial size of VM memory > + * and sleep for decent period (downtime for example). */ > + sleeptime_mcs =3D migrate_max_downtime()/1000; > + initial_bytes =3D remaining_bytes; > + usleep(sleeptime_mcs); > + break; > + case 1: > + /* Second and last call. > + * We assume that time between two synchronizations of > + * dirty bitmap differs from downtime negligibly and > + * make our estimation of dirty bytes rate. */ > + dirtied_bytes =3D remaining_bytes; > + time_delta =3D sleeptime_mcs / 1000; > + s->dirty_bytes_rate =3D dirtied_bytes * 1000 / time_delta; > + return -42; > + default: > + /* All calls after second are errors */ > + return -1; > + } > + return 0; > +} > + > static const QEMUFileOps test_write_ops =3D { > + .hook_ram_sync =3D qemu_test_sync_hook, > .put_buffer =3D qemu_test_put_buffer, > .close =3D qemu_test_close, > }; > @@ -41,6 +76,7 @@ static void *qemu_fopen_test(MigrationState *s, const= char *mode) > QEMUFileTest *t; > transfered_bytes =3D 0; > initial_bytes =3D 0; > + sync_cnt =3D 0; > if (qemu_file_mode_is_not_valid(mode)) { > return NULL; > } > --=20 > 2.1.4 >=20 >=20 -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK