Mailing List Archive

[PATCH 7 of 7] xenalyze: Analyze populate-on-demand reclamation patterns
# HG changeset patch
# User George Dunlap <george.dunlap@eu.citrix.com>
# Date 1349264664 -3600
# Node ID 393e0ead61a506f8bd1dea55ed7b3611ec4c7c1f
# Parent 703cd2301a0a04934d30c7e4f7357df82ed12677
xenalyze: Analyze populate-on-demand reclamation patterns

This includes attempting to classify each reclamation to see if it was
the result of a fault or of ballooning, as well as tracking the order
of the pages reclaimed.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>

diff --git a/xenalyze.c b/xenalyze.c
--- a/xenalyze.c
+++ b/xenalyze.c
@@ -1723,6 +1723,21 @@ char * domain_runstate_name[] = {
[DOMAIN_RUNSTATE_LOST]="lost",
};

+enum {
+ POD_RECLAIM_CONTEXT_UNKNOWN=0,
+ POD_RECLAIM_CONTEXT_FAULT,
+ POD_RECLAIM_CONTEXT_BALLOON,
+ POD_RECLAIM_CONTEXT_MAX
+};
+
+char * pod_reclaim_context_name[] = {
+ [POD_RECLAIM_CONTEXT_UNKNOWN]="unknown",
+ [POD_RECLAIM_CONTEXT_FAULT]="fault",
+ [POD_RECLAIM_CONTEXT_BALLOON]="balloon",
+};
+
+#define POD_ORDER_MAX 4
+
struct domain_data {
struct domain_data *next;
int did;
@@ -1747,6 +1762,14 @@ struct domain_data {
int done_for[MEM_MAX];
int done_for_interval[MEM_MAX];
} memops;
+
+ struct {
+ int reclaim_order[POD_ORDER_MAX];
+ int reclaim_context[POD_RECLAIM_CONTEXT_MAX];
+ int reclaim_context_order[POD_RECLAIM_CONTEXT_MAX][POD_ORDER_MAX];
+ /* FIXME: Do a full cycle summary */
+ int populate_order[POD_ORDER_MAX];
+ } pod;
};

struct domain_data * domain_list=NULL;
@@ -7396,7 +7419,7 @@ void sched_process(struct pcpu_info *p)

/* ---- Memory ---- */
void mem_summary_domain(struct domain_data *d) {
- int i;
+ int i, j;

printf(" Grant table ops:\n");

@@ -7413,23 +7436,103 @@ void mem_summary_domain(struct domain_da
printf(" %-14s: %d\n",
mem_name[i],
d->memops.done_for[i]);
+
+ printf(" Populate-on-demand:\n");
+ printf(" Populated:\n");
+ for(i=0; i<4; i++)
+ {
+ if ( d->pod.populate_order[i] )
+ printf(" [%d] %d\n", i,
+ d->pod.populate_order[i]);
+ }
+ printf(" Reclaim order:\n");
+ for(i=0; i<4; i++)
+ {
+ if ( d->pod.reclaim_order[i] )
+ printf(" [%d] %d\n", i,
+ d->pod.reclaim_order[i]);
+ }
+ printf(" Reclaim contexts:\n");
+ for(j=0; j<POD_RECLAIM_CONTEXT_MAX; j++)
+ {
+ if ( d->pod.reclaim_context[j] )
+ {
+ printf(" * [%s] %d\n",
+ pod_reclaim_context_name[j],
+ d->pod.reclaim_context[j]);
+ for(i=0; i<4; i++)
+ {
+ if ( d->pod.reclaim_context_order[j][i] )
+ printf(" [%d] %d\n", i,
+ d->pod.reclaim_context_order[j][i]);
+ }
+ }
+ }
+}
+
+int p2m_canonical_order(int order)
+{
+ if ( order % 9
+ || (order / 9) > 2 )
+ {
+ fprintf(warn, "%s: Strange, non-canonical order %d\n",
+ __func__, order);
+ order = 4;
+ } else {
+ order /= 9;
+ }
+ return order;
}

void mem_pod_zero_reclaim_process(struct pcpu_info *p)
{
struct record_info *ri = &p->ri;
+ int context = POD_RECLAIM_CONTEXT_UNKNOWN;
+ struct vcpu_data *v = p->current;

struct {
uint64_t gfn, mfn;
int d:16,order:16;
} *r = (typeof(r))ri->d;

+ if ( v && v->hvm.vmexit_valid )
+ {
+ switch(v->hvm.exit_reason)
+ {
+ case EXIT_REASON_EPT_VIOLATION:
+ case EXIT_REASON_EXCEPTION_NMI:
+ context = POD_RECLAIM_CONTEXT_FAULT;
+ break;
+ case EXIT_REASON_VMCALL:
+ context = POD_RECLAIM_CONTEXT_BALLOON;
+ break;
+ }
+ }
+
if ( opt.dump_all )
{
- printf(" %s pod_zero_reclaim d%d o%d g %llx m %llx\n",
+ printf(" %s pod_zero_reclaim d%d o%d g %llx m %llx ctx %s\n",
ri->dump_header,
r->d, r->order,
- (unsigned long long)r->gfn, (unsigned long long)r->mfn);
+ (unsigned long long)r->gfn, (unsigned long long)r->mfn,
+ pod_reclaim_context_name[context]);
+
+ }
+
+ if ( opt.summary_info )
+ {
+ struct domain_data *d;
+
+ if ( v && (d=v->d) )
+ {
+ int order;
+
+ order = p2m_canonical_order(r->order);
+
+ d->pod.reclaim_order[order]++;
+ d->pod.reclaim_context[context]++;
+ d->pod.reclaim_context_order[context][order]++;
+ }
}
}

@@ -7449,6 +7552,21 @@ void mem_pod_populate_process(struct pcp
r->d, r->order,
(unsigned long long)r->gfn, (unsigned long long)r->mfn);
}
+
+ if ( opt.summary_info )
+ {
+ struct vcpu_data *v = p->current;
+ struct domain_data *d;
+
+ if ( v && (d=v->d) )
+ {
+ int order;
+
+ order = p2m_canonical_order(r->order);
+
+ d->pod.populate_order[order]++;
+ }
+ }
}

void mem_pod_superpage_splinter_process(struct pcpu_info *p)

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel