From owner-svn-src-all@FreeBSD.ORG Fri May 7 19:48:51 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 18EEC1065670; Fri, 7 May 2010 19:48:51 +0000 (UTC) (envelope-from fabient@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [69.147.83.44]) by mx1.freebsd.org (Postfix) with ESMTP id 074C18FC12; Fri, 7 May 2010 19:48:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o47JmoRx093417; Fri, 7 May 2010 19:48:50 GMT (envelope-from fabient@svn.freebsd.org) Received: (from fabient@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o47JmooH093415; Fri, 7 May 2010 19:48:50 GMT (envelope-from fabient@svn.freebsd.org) Message-Id: <201005071948.o47JmooH093415@svn.freebsd.org> From: Fabien Thomas Date: Fri, 7 May 2010 19:48:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r207755 - head/usr.sbin/pmcstat X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 07 May 2010 19:48:51 -0000 Author: fabient Date: Fri May 7 19:48:50 2010 New Revision: 207755 URL: http://svn.freebsd.org/changeset/base/207755 Log: Rework the calltree top view by critical callchain. The percentage show is the sum of the cost for the codepath. MFC after: 1 week Modified: head/usr.sbin/pmcstat/pmcpl_calltree.c Modified: head/usr.sbin/pmcstat/pmcpl_calltree.c ============================================================================== --- head/usr.sbin/pmcstat/pmcpl_calltree.c Fri May 7 19:02:31 2010 (r207754) +++ head/usr.sbin/pmcstat/pmcpl_calltree.c Fri May 7 19:48:50 2010 (r207755) @@ -120,8 +120,15 @@ struct pmcpl_ct_node_hash { struct pmcpl_ct_sample pmcpl_ct_callid; #define PMCPL_CT_MAXCOL PMC_CALLCHAIN_DEPTH_MAX -#define PMCPL_CT_MAXLINE 256 -struct pmcpl_ct_node *pmcpl_ct_topscreen[PMCPL_CT_MAXCOL][PMCPL_CT_MAXLINE]; +#define PMCPL_CT_MAXLINE 1024 /* TODO: dynamic. */ + +struct pmcpl_ct_line { + unsigned ln_sum; + unsigned ln_index; +}; + +struct pmcpl_ct_line pmcpl_ct_topmax[PMCPL_CT_MAXLINE+1]; +struct pmcpl_ct_node *pmcpl_ct_topscreen[PMCPL_CT_MAXCOL+1][PMCPL_CT_MAXLINE+1]; /* * All nodes indexed by function/image name are placed in a hash table. @@ -225,28 +232,6 @@ pmcpl_ct_arc_grow(int cursize, int *maxs } /* - * Compare two arc by samples value. - */ -static int -pmcpl_ct_arc_compare(void *thunk, const void *a, const void *b) -{ - const struct pmcpl_ct_arc *ct1, *ct2; - int pmcin = *(int *)thunk; - - ct1 = (const struct pmcpl_ct_arc *) a; - ct2 = (const struct pmcpl_ct_arc *) b; - - /* Sort in reverse order */ - if (PMCPL_CT_SAMPLE(pmcin, &ct1->pcta_samples) < - PMCPL_CT_SAMPLE(pmcin, &ct2->pcta_samples)) - return (1); - if (PMCPL_CT_SAMPLE(pmcin, &ct1->pcta_samples) > - PMCPL_CT_SAMPLE(pmcin, &ct2->pcta_samples)) - return (-1); - return (0); -} - -/* * Grow the instr table. */ @@ -366,9 +351,9 @@ pmcpl_ct_node_cleartag(void) static int pmcpl_ct_node_dumptop(int pmcin, struct pmcpl_ct_node *ct, - struct pmcpl_ct_sample *rsamples, int x, int *y, int maxy) + struct pmcpl_ct_sample *rsamples, int x, int *y) { - int i; + int i, terminal; if (ct->pct_flags & PMCPL_PCT_TAG) return 0; @@ -382,12 +367,21 @@ pmcpl_ct_node_dumptop(int pmcin, struct pmcpl_ct_topscreen[x][*y] = ct; /* - * This is a terminal node + * Check if this is a terminal node. + * We need to check that some samples exist + * for at least one arc for that PMC. */ - if (ct->pct_narc == 0) { + terminal = 1; + for (i = 0; i < ct->pct_narc; i++) + if (PMCPL_CT_SAMPLE(pmcin, + &ct->pct_arc[i].pcta_samples) != 0) { + terminal = 0; + break; + } + + if (ct->pct_narc == 0 || terminal) { pmcpl_ct_topscreen[x+1][*y] = NULL; - if (*y >= PMCPL_CT_MAXLINE || - *y >= maxy) + if (*y >= PMCPL_CT_MAXLINE) return 1; *y = *y + 1; for (i=0; i < x; i++) @@ -396,14 +390,7 @@ pmcpl_ct_node_dumptop(int pmcin, struct return 0; } - /* - * Quicksort the arcs. - */ - qsort_r(ct->pct_arc, ct->pct_narc, sizeof(struct pmcpl_ct_arc), - &pmcin, pmcpl_ct_arc_compare); - for (i = 0; i < ct->pct_narc; i++) { - /* Skip this arc if there is no sample at all. */ if (PMCPL_CT_SAMPLE(pmcin, &ct->pct_arc[i].pcta_samples) == 0) continue; @@ -411,7 +398,7 @@ pmcpl_ct_node_dumptop(int pmcin, struct &ct->pct_arc[i].pcta_samples) > pmcstat_threshold) { if (pmcpl_ct_node_dumptop(pmcin, ct->pct_arc[i].pcta_child, - rsamples, x+1, y, maxy)) + rsamples, x+1, y)) return 1; } } @@ -420,12 +407,36 @@ pmcpl_ct_node_dumptop(int pmcin, struct } /* + * Compare two top line by sum. + */ +static int +pmcpl_ct_line_compare(const void *a, const void *b) +{ + const struct pmcpl_ct_line *ct1, *ct2; + + ct1 = (const struct pmcpl_ct_line *) a; + ct2 = (const struct pmcpl_ct_line *) b; + + /* Sort in reverse order */ + if (ct1->ln_sum < ct2->ln_sum) + return (1); + if (ct1->ln_sum > ct2->ln_sum) + return (-1); + return (0); +} + +/* * Format and display given PMC index. */ static void pmcpl_ct_node_printtop(struct pmcpl_ct_sample *rsamples, int pmcin, int maxy) { +#undef TS +#undef TSI +#define TS(x, y) (pmcpl_ct_topscreen[x][y]) +#define TSI(x, y) (pmcpl_ct_topscreen[x][pmcpl_ct_topmax[y].ln_index]) + int v_attrs, ns_len, vs_len, is_len, width, indentwidth, x, y; float v; char ns[30], vs[10], is[20]; @@ -433,33 +444,60 @@ pmcpl_ct_node_printtop(struct pmcpl_ct_s struct pmcstat_symbol *sym; const char *space = " "; + /* + * Sort by line cost. + */ + for (y = 0; ; y++) { + ct = TS(1, y); + if (ct == NULL) + break; + + pmcpl_ct_topmax[y].ln_sum = 0; + pmcpl_ct_topmax[y].ln_index = y; + for (x = 1; TS(x, y) != NULL; x++) { + pmcpl_ct_topmax[y].ln_sum += + PMCPL_CT_SAMPLE(pmcin, &TS(x, y)->pct_samples); + } + } + qsort(pmcpl_ct_topmax, y, sizeof(pmcpl_ct_topmax[0]), + pmcpl_ct_line_compare); + pmcpl_ct_topmax[y].ln_index = y; + for (y = 0; y < maxy; y++) { - /* Output image. */ - ct = pmcpl_ct_topscreen[0][y]; - snprintf(is, sizeof(is), "%-10.10s", - pmcstat_string_unintern(ct->pct_image->pi_name)); - PMCSTAT_PRINTW("%s ", is); - width = indentwidth = 11; + ct = TSI(1, y); + if (ct == NULL) + break; - for (x = 0; pmcpl_ct_topscreen[x][y] !=NULL; x++) { + if (y > 0) + PMCSTAT_PRINTW("\n"); - ct = pmcpl_ct_topscreen[x][y]; + /* Output sum. */ + v = pmcpl_ct_topmax[y].ln_sum * 100.0 / + rsamples->sb[pmcin]; + snprintf(vs, sizeof(vs), "%.1f", v); + v_attrs = PMCSTAT_ATTRPERCENT(v); + PMCSTAT_ATTRON(v_attrs); + PMCSTAT_PRINTW("%5.5s ", vs); + PMCSTAT_ATTROFF(v_attrs); + + width = indentwidth = 5 + 1; + + for (x = 1; (ct = TSI(x, y)) != NULL; x++) { - ns[0] = '\0'; ns_len = 0; vs[0] = '\0'; vs_len = 0; is[0] = '\0'; is_len = 0; /* Format value. */ v = PMCPL_CT_SAMPLEP(pmcin, &ct->pct_samples); if (v > pmcstat_threshold) - vs_len = snprintf(vs, sizeof(vs), "(%.1f%%)", v); + vs_len = snprintf(vs, sizeof(vs), + "(%.1f%%)", v); v_attrs = PMCSTAT_ATTRPERCENT(v); if (pmcstat_skiplink && v <= pmcstat_threshold) { - PMCSTAT_PRINTW(". "); - width += 2; - continue; - } + strlcpy(ns, ".", sizeof(ns)); + ns_len = 1; + } else { sym = pmcstat_symbol_search(ct->pct_image, ct->pct_func); if (sym != NULL) { ns_len = snprintf(ns, sizeof(ns), "%s", @@ -469,12 +507,14 @@ pmcpl_ct_node_printtop(struct pmcpl_ct_s (void *)ct->pct_func); /* Format image. */ - if (x > 0 && pmcpl_ct_topscreen[x-1][y]->pct_image != ct->pct_image) + if (x == 1 || + TSI(x-1, y)->pct_image != ct->pct_image) is_len = snprintf(is, sizeof(is), "@%s", pmcstat_string_unintern(ct->pct_image->pi_name)); /* Check for line wrap. */ width += ns_len + is_len + vs_len + 1; + } if (width >= pmcstat_displaywidth) { maxy--; if (y >= maxy) @@ -487,7 +527,6 @@ pmcpl_ct_node_printtop(struct pmcpl_ct_s PMCSTAT_PRINTW("%s%s%s ", ns, is, vs); PMCSTAT_ATTROFF(v_attrs); } - PMCSTAT_PRINTW("\n"); } } @@ -498,46 +537,25 @@ pmcpl_ct_node_printtop(struct pmcpl_ct_s void pmcpl_ct_topdisplay(void) { - int i, x, y, pmcin; + int y; struct pmcpl_ct_sample r, *rsamples; rsamples = &r; pmcpl_ct_samples_root(rsamples); - PMCSTAT_PRINTW("%-10.10s %s\n", "IMAGE", "CALLTREE"); + pmcpl_ct_node_cleartag(); - for (pmcin = 0; pmcin < pmcstat_npmcs; pmcin++) { - /* Filter PMCs. */ - if (pmcstat_pmcinfilter != pmcin) - continue; + PMCSTAT_PRINTW("%5.5s %s\n", "%SAMP", "CALLTREE"); - pmcpl_ct_node_cleartag(); + y = 0; + if (pmcpl_ct_node_dumptop(pmcstat_pmcinfilter, + pmcpl_ct_root, rsamples, 0, &y)) + PMCSTAT_PRINTW("...\n"); + pmcpl_ct_topscreen[1][y] = NULL; - /* Quicksort the arcs. */ - qsort_r(pmcpl_ct_root->pct_arc, - pmcpl_ct_root->pct_narc, - sizeof(struct pmcpl_ct_arc), - &pmcin, pmcpl_ct_arc_compare); - - x = y = 0; - for (i = 0; i < pmcpl_ct_root->pct_narc; i++) { - /* Skip this arc if there is no sample at all. */ - if (PMCPL_CT_SAMPLE(pmcin, - &pmcpl_ct_root->pct_arc[i].pcta_samples) == 0) - continue; - if (PMCPL_CT_SAMPLEP(pmcin, - &pmcpl_ct_root->pct_arc[i].pcta_samples) <= - pmcstat_threshold) - continue; - if (pmcpl_ct_node_dumptop(pmcin, - pmcpl_ct_root->pct_arc[i].pcta_child, - rsamples, x, &y, pmcstat_displayheight - 2)) { - break; - } - } + pmcpl_ct_node_printtop(rsamples, + pmcstat_pmcinfilter, pmcstat_displayheight - 2); - pmcpl_ct_node_printtop(rsamples, pmcin, y); - } pmcpl_ct_samples_free(rsamples); }