[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 7 of 7] xenalyze: Analyze populate-on-demand reclamation patterns



# HG changeset patch
# User George Dunlap <george.dunlap@xxxxxxxxxxxxx>
# 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@xxxxxxxxxxxxx>

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@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.