[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v6 3/3] tools/libxc: use superpages during restore of HVM guest
On Sat, Aug 26, Olaf Hering wrote: > +static int x86_hvm_populate_pfns(struct xc_sr_context *ctx, unsigned count, > + /* > + * Scan the entire superpage because several batches will fit into > + * a superpage, and it is unknown which pfn triggered the allocation. > + */ > + order = SUPERPAGE_1GB_SHIFT; > + pfn = min_pfn = (min_pfn >> order) << order; Scanning an entire superpage again and again looked expensive, but with the debug change below it turned out that the loop which peeks at each single bit in populated_pfns is likely not a bootleneck. Migrating a domU with a simple workload that touches pages to mark them dirty will set the min_pfn/max_pfn to a large range anyway after the first iteration. This large range may also happen with an idle domU. A small domU takes 78 seconds to migrate, and just the freeing part takes 1.4 seconds. Similar for a large domain, the loop takes 1% of the time. 78 seconds, 1.4 seconds, 2119 calls (8GB, 12*512M memdirty) 695 seconds, 7.6 seconds, 18076 calls (72GB, 12*5G memdirty) Olaf track time spent if decrease_reservation is needed diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h index 0fa0fbea4d..5ec8b6fee6 100644 --- a/tools/libxc/xc_sr_common.h +++ b/tools/libxc/xc_sr_common.h @@ -353,6 +353,9 @@ struct xc_sr_context struct xc_sr_bitmap attempted_1g; struct xc_sr_bitmap attempted_2m; struct xc_sr_bitmap allocated_pfns; + + unsigned long tv_nsec; + unsigned long iterations; } restore; }; } x86_hvm; diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c index 8cd9289d1a..f6aad329e2 100644 --- a/tools/libxc/xc_sr_restore.c +++ b/tools/libxc/xc_sr_restore.c @@ -769,6 +769,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, { ctx.restore.ops = restore_ops_x86_hvm; if ( restore(&ctx) ) + ; return -1; } else diff --git a/tools/libxc/xc_sr_restore_x86_hvm.c b/tools/libxc/xc_sr_restore_x86_hvm.c index 2b0eca0c7c..11758b3f7d 100644 --- a/tools/libxc/xc_sr_restore_x86_hvm.c +++ b/tools/libxc/xc_sr_restore_x86_hvm.c @@ -1,5 +1,6 @@ #include <assert.h> #include <arpa/inet.h> +#include <time.h> #include "xc_sr_common_x86.h" @@ -248,6 +249,12 @@ static int x86_hvm_stream_complete(struct xc_sr_context *ctx) static int x86_hvm_cleanup(struct xc_sr_context *ctx) { + xc_interface *xch = ctx->xch; + errno = 0; + PERROR("tv_nsec %lu.%lu iterations %lu", + ctx->x86_hvm.restore.tv_nsec / 1000000000UL, + ctx->x86_hvm.restore.tv_nsec % 1000000000UL, + ctx->x86_hvm.restore.iterations); free(ctx->x86_hvm.restore.context); xc_sr_bitmap_free(&ctx->x86_hvm.restore.attempted_1g); xc_sr_bitmap_free(&ctx->x86_hvm.restore.attempted_2m); @@ -440,6 +447,28 @@ static int x86_hvm_allocate_pfn(struct xc_sr_context *ctx, xen_pfn_t pfn) return rc; } +static void diff_timespec(struct xc_sr_context *ctx, const struct timespec *old, const struct timespec *new, struct timespec *diff) +{ + xc_interface *xch = ctx->xch; + if (new->tv_sec == old->tv_sec && new->tv_nsec == old->tv_nsec) + PERROR("%s: time did not move: %ld/%ld == %ld/%ld", __func__, old->tv_sec, old->tv_nsec, new->tv_sec, new->tv_nsec); + if ( (new->tv_sec < old->tv_sec) || (new->tv_sec == old->tv_sec && new->tv_nsec < old->tv_nsec) ) + { + PERROR("%s: time went backwards: %ld/%ld -> %ld/%ld", __func__, old->tv_sec, old->tv_nsec, new->tv_sec, new->tv_nsec); + diff->tv_sec = diff->tv_nsec = 0; + return; + } + if ((new->tv_nsec - old->tv_nsec) < 0) { + diff->tv_sec = new->tv_sec - old->tv_sec - 1; + diff->tv_nsec = new->tv_nsec - old->tv_nsec + 1000000000UL; + } else { + diff->tv_sec = new->tv_sec - old->tv_sec; + diff->tv_nsec = new->tv_nsec - old->tv_nsec; + } + if (diff->tv_sec < 0) + PERROR("%s: time diff broken. old: %ld/%ld new: %ld/%ld diff: %ld/%ld ", __func__, old->tv_sec, old->tv_nsec, new->tv_sec, new->tv_nsec, diff->tv_sec, diff->tv_nsec); +} + static int x86_hvm_populate_pfns(struct xc_sr_context *ctx, unsigned count, const xen_pfn_t *original_pfns, const uint32_t *types) @@ -448,6 +477,7 @@ static int x86_hvm_populate_pfns(struct xc_sr_context *ctx, unsigned count, xen_pfn_t pfn, min_pfn = original_pfns[0], max_pfn = original_pfns[0]; unsigned i, freed = 0, order; int rc = -1; + struct timespec a, b, d; for ( i = 0; i < count; ++i ) { @@ -474,6 +504,8 @@ static int x86_hvm_populate_pfns(struct xc_sr_context *ctx, unsigned count, } } + if (clock_gettime(CLOCK_MONOTONIC, &a)) + PERROR("clock_gettime start"); /* * Scan the entire superpage because several batches will fit into * a superpage, and it is unknown which pfn triggered the allocation. @@ -504,10 +536,17 @@ static int x86_hvm_populate_pfns(struct xc_sr_context *ctx, unsigned count, } pfn++; } - if ( freed ) + if ( 0 && freed ) DPRINTF("freed %u between %" PRI_xen_pfn " %" PRI_xen_pfn "\n", freed, min_pfn, max_pfn); + if (clock_gettime(CLOCK_MONOTONIC, &b)) + PERROR("clock_gettime end"); + + diff_timespec(ctx, &a, &b, &d); + ctx->x86_hvm.restore.tv_nsec += d.tv_nsec + (1000000000UL * d.tv_sec); + ctx->x86_hvm.restore.iterations++; + rc = 0; err: Attachment:
signature.asc _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |