Print this page
4471 DTrace count() with histogram
4472 DTrace full width distribution histograms
4473 DTrace frequency trails

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libdtrace/common/dt_consume.c
          +++ new/usr/src/lib/libdtrace/common/dt_consume.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  /*
  27      - * Copyright (c) 2011, Joyent, Inc. All rights reserved.
       27 + * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  28   28   * Copyright (c) 2012 by Delphix. All rights reserved.
  29   29   */
  30   30  
  31   31  #include <stdlib.h>
  32   32  #include <strings.h>
  33   33  #include <errno.h>
  34   34  #include <unistd.h>
  35   35  #include <limits.h>
  36   36  #include <assert.h>
  37   37  #include <ctype.h>
↓ open down ↓ 9 lines elided ↑ open up ↑
  47   47   */
  48   48  static long double
  49   49  dt_fabsl(long double x)
  50   50  {
  51   51          if (x < 0)
  52   52                  return (-x);
  53   53  
  54   54          return (x);
  55   55  }
  56   56  
       57 +static int
       58 +dt_ndigits(long long val)
       59 +{
       60 +        int rval = 1;
       61 +        long long cmp = 10;
       62 +
       63 +        if (val < 0) {
       64 +                val = val == INT64_MIN ? INT64_MAX : -val;
       65 +                rval++;
       66 +        }
       67 +
       68 +        while (val > cmp && cmp > 0) {
       69 +                rval++;
       70 +                cmp *= 10;
       71 +        }
       72 +
       73 +        return (rval < 4 ? 4 : rval);
       74 +}
       75 +
  57   76  /*
  58   77   * 128-bit arithmetic functions needed to support the stddev() aggregating
  59   78   * action.
  60   79   */
  61   80  static int
  62   81  dt_gt_128(uint64_t *a, uint64_t *b)
  63   82  {
  64   83          return (a[1] > b[1] || (a[1] == b[1] && a[0] > b[0]));
  65   84  }
  66   85  
↓ open down ↓ 408 lines elided ↑ open up ↑
 475  494  {
 476  495          return (DTRACE_CONSUME_THIS);
 477  496  }
 478  497  
 479  498  static int
 480  499  dt_nullrec()
 481  500  {
 482  501          return (DTRACE_CONSUME_NEXT);
 483  502  }
 484  503  
 485      -int
      504 +static void
      505 +dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
      506 +{
      507 +        long double val = dt_fabsl((long double)datum);
      508 +
      509 +        if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
      510 +                *total += val;
      511 +                return;
      512 +        }
      513 +
      514 +        /*
      515 +         * If we're zooming in on an aggregation, we want the height of the
      516 +         * highest value to be approximately 95% of total bar height -- so we
      517 +         * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
      518 +         * our highest value.
      519 +         */
      520 +        val *= 1 / DTRACE_AGGZOOM_MAX;
      521 +
      522 +        if (*total < val)
      523 +                *total = val;
      524 +}
      525 +
      526 +static int
      527 +dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
      528 +{
      529 +        return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
      530 +            width ? width : 16, width ? "key" : "value",
      531 +            "------------- Distribution -------------", "count"));
      532 +}
      533 +
      534 +static int
      535 +dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
      536 +    const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
      537 +{
      538 +        int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
      539 +        int minwidth, maxwidth, i;
      540 +
      541 +        assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
      542 +
      543 +        if (action == DTRACEAGG_QUANTIZE) {
      544 +                if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
      545 +                        min--;
      546 +
      547 +                if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
      548 +                        max++;
      549 +
      550 +                minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
      551 +                maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
      552 +        } else {
      553 +                maxwidth = 8;
      554 +                minwidth = maxwidth - 1;
      555 +                max++;
      556 +        }
      557 +
      558 +        if (dt_printf(dtp, fp, "\n%*s %*s .",
      559 +            width, width > 0 ? "key" : "", minwidth, "min") < 0)
      560 +                return (-1);
      561 +
      562 +        for (i = min; i <= max; i++) {
      563 +                if (dt_printf(dtp, fp, "-") < 0)
      564 +                        return (-1);
      565 +        }
      566 +
      567 +        return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
      568 +}
      569 +
      570 +/*
      571 + * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
      572 + * inclusive) to represent aggregations via UTF-8 -- which are expressed via
      573 + * 3-byte UTF-8 sequences.
      574 + */
      575 +#define DTRACE_AGGUTF8_FULL     0x2588
      576 +#define DTRACE_AGGUTF8_BASE     0x258f
      577 +#define DTRACE_AGGUTF8_LEVELS   8
      578 +
      579 +#define DTRACE_AGGUTF8_BYTE0(val)       (0xe0 | ((val) >> 12))
      580 +#define DTRACE_AGGUTF8_BYTE1(val)       (0x80 | (((val) >> 6) & 0x3f))
      581 +#define DTRACE_AGGUTF8_BYTE2(val)       (0x80 | ((val) & 0x3f))
      582 +
      583 +static int
      584 +dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
      585 +    uint64_t normal, long double total)
      586 +{
      587 +        uint_t len = 40, i, whole, partial;
      588 +        long double f = (dt_fabsl((long double)val) * len) / total;
      589 +        const char *spaces = "                                        ";
      590 +
      591 +        whole = (uint_t)f;
      592 +        partial = (uint_t)((f - (long double)(uint_t)f) *
      593 +            (long double)DTRACE_AGGUTF8_LEVELS);
      594 +
      595 +        if (dt_printf(dtp, fp, "|") < 0)
      596 +                return (-1);
      597 +
      598 +        for (i = 0; i < whole; i++) {
      599 +                if (dt_printf(dtp, fp, "%c%c%c",
      600 +                    DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
      601 +                    DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
      602 +                    DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
      603 +                        return (-1);
      604 +        }
      605 +
      606 +        if (partial != 0) {
      607 +                partial = DTRACE_AGGUTF8_BASE - (partial - 1);
      608 +
      609 +                if (dt_printf(dtp, fp, "%c%c%c",
      610 +                    DTRACE_AGGUTF8_BYTE0(partial),
      611 +                    DTRACE_AGGUTF8_BYTE1(partial),
      612 +                    DTRACE_AGGUTF8_BYTE2(partial)) < 0)
      613 +                        return (-1);
      614 +
      615 +                i++;
      616 +        }
      617 +
      618 +        return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
      619 +            (long long)val / normal));
      620 +}
      621 +
      622 +static int
 486  623  dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
 487  624      uint64_t normal, long double total, char positives, char negatives)
 488  625  {
 489  626          long double f;
 490  627          uint_t depth, len = 40;
 491  628  
 492  629          const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
 493  630          const char *spaces = "                                        ";
 494  631  
 495  632          assert(strlen(ats) == len && strlen(spaces) == len);
 496  633          assert(!(total == 0 && (positives || negatives)));
 497  634          assert(!(val < 0 && !negatives));
 498  635          assert(!(val > 0 && !positives));
 499  636          assert(!(val != 0 && total == 0));
 500  637  
 501  638          if (!negatives) {
 502  639                  if (positives) {
      640 +                        if (dtp->dt_encoding == DT_ENCODING_UTF8) {
      641 +                                return (dt_print_quantline_utf8(dtp, fp, val,
      642 +                                    normal, total));
      643 +                        }
      644 +
 503  645                          f = (dt_fabsl((long double)val) * len) / total;
 504  646                          depth = (uint_t)(f + 0.5);
 505  647                  } else {
 506  648                          depth = 0;
 507  649                  }
 508  650  
 509  651                  return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth,
 510  652                      spaces + depth, (long long)val / normal));
 511  653          }
 512  654  
↓ open down ↓ 22 lines elided ↑ open up ↑
 535  677          if (val <= 0) {
 536  678                  return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth,
 537  679                      ats + len - depth, len, "", (long long)val / normal));
 538  680          } else {
 539  681                  return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "",
 540  682                      ats + len - depth, spaces + depth,
 541  683                      (long long)val / normal));
 542  684          }
 543  685  }
 544  686  
      687 +/*
      688 + * As with UTF-8 printing of aggregations, we use a subset of the Unicode
      689 + * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
      690 + * aggregation.
      691 + */
      692 +#define DTRACE_AGGPACK_BASE     0x2581
      693 +#define DTRACE_AGGPACK_LEVELS   8
      694 +
      695 +static int
      696 +dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
      697 +    long double datum, long double total)
      698 +{
      699 +        static boolean_t utf8_checked = B_FALSE;
      700 +        static boolean_t utf8;
      701 +        char *ascii = "__xxxxXX";
      702 +        char *neg = "vvvvVV";
      703 +        unsigned int len;
      704 +        long double val;
      705 +
      706 +        if (!utf8_checked) {
      707 +                char *term;
      708 +
      709 +                /*
      710 +                 * We want to determine if we can reasonably emit UTF-8 for our
      711 +                 * packed aggregation.  To do this, we will check for terminals
      712 +                 * that are known to be primitive to emit UTF-8 on these.
      713 +                 */
      714 +                utf8_checked = B_TRUE;
      715 +
      716 +                if (dtp->dt_encoding == DT_ENCODING_ASCII)
      717 +                        utf8 = B_FALSE;
      718 +                else if (dtp->dt_encoding == DT_ENCODING_UTF8)
      719 +                        utf8 = B_TRUE;
      720 +                else if ((term = getenv("TERM")) != NULL &&
      721 +                    (strcmp(term, "sun") == 0 ||
      722 +                    strcmp(term, "sun-color") == 0) ||
      723 +                    strcmp(term, "dumb") == 0)
      724 +                        utf8 = B_FALSE;
      725 +                else
      726 +                        utf8 = B_TRUE;
      727 +        }
      728 +
      729 +        if (datum == 0)
      730 +                return (dt_printf(dtp, fp, " "));
      731 +
      732 +        if (datum < 0) {
      733 +                len = strlen(neg);
      734 +                val = dt_fabsl(datum * (len - 1)) / total;
      735 +                return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
      736 +        }
      737 +
      738 +        if (utf8) {
      739 +                int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
      740 +                    (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
      741 +
      742 +                return (dt_printf(dtp, fp, "%c%c%c",
      743 +                    DTRACE_AGGUTF8_BYTE0(block),
      744 +                    DTRACE_AGGUTF8_BYTE1(block),
      745 +                    DTRACE_AGGUTF8_BYTE2(block)));
      746 +        }
      747 +
      748 +        len = strlen(ascii);
      749 +        val = (datum * (len - 1)) / total;
      750 +        return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
      751 +}
      752 +
 545  753  int
 546  754  dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 547  755      size_t size, uint64_t normal)
 548  756  {
 549  757          const int64_t *data = addr;
 550  758          int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
 551  759          long double total = 0;
 552  760          char positives = 0, negatives = 0;
 553  761  
 554  762          if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
 555  763                  return (dt_set_errno(dtp, EDT_DMISMATCH));
 556  764  
 557  765          while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
 558  766                  first_bin++;
 559  767  
 560  768          if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
 561  769                  /*
 562      -                 * There isn't any data.  This is possible if (and only if)
 563      -                 * negative increment values have been used.  In this case,
 564      -                 * we'll print the buckets around 0.
      770 +                 * There isn't any data.  This is possible if the aggregation
      771 +                 * has been clear()'d or if negative increment values have been
      772 +                 * used.  Regardless, we'll print the buckets around 0.
 565  773                   */
 566  774                  first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
 567  775                  last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
 568  776          } else {
 569  777                  if (first_bin > 0)
 570  778                          first_bin--;
 571  779  
 572  780                  while (last_bin > 0 && data[last_bin] == 0)
 573  781                          last_bin--;
 574  782  
 575  783                  if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)
 576  784                          last_bin++;
 577  785          }
 578  786  
 579  787          for (i = first_bin; i <= last_bin; i++) {
 580  788                  positives |= (data[i] > 0);
 581  789                  negatives |= (data[i] < 0);
 582      -                total += dt_fabsl((long double)data[i]);
      790 +                dt_quantize_total(dtp, data[i], &total);
 583  791          }
 584  792  
 585      -        if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
 586      -            "------------- Distribution -------------", "count") < 0)
      793 +        if (dt_print_quanthdr(dtp, fp, 0) < 0)
 587  794                  return (-1);
 588  795  
 589  796          for (i = first_bin; i <= last_bin; i++) {
 590  797                  if (dt_printf(dtp, fp, "%16lld ",
 591  798                      (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
 592  799                          return (-1);
 593  800  
 594  801                  if (dt_print_quantline(dtp, fp, data[i], normal, total,
 595  802                      positives, negatives) < 0)
 596  803                          return (-1);
 597  804          }
 598  805  
 599  806          return (0);
 600  807  }
 601  808  
 602  809  int
      810 +dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
      811 +    size_t size, const dtrace_aggdata_t *aggdata)
      812 +{
      813 +        const int64_t *data = addr;
      814 +        long double total = 0, count = 0;
      815 +        int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
      816 +        int64_t minval, maxval;
      817 +
      818 +        if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
      819 +                return (dt_set_errno(dtp, EDT_DMISMATCH));
      820 +
      821 +        if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
      822 +                min--;
      823 +
      824 +        if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
      825 +                max++;
      826 +
      827 +        minval = DTRACE_QUANTIZE_BUCKETVAL(min);
      828 +        maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
      829 +
      830 +        if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
      831 +            (long long)minval) < 0)
      832 +                return (-1);
      833 +
      834 +        for (i = min; i <= max; i++) {
      835 +                dt_quantize_total(dtp, data[i], &total);
      836 +                count += data[i];
      837 +        }
      838 +
      839 +        for (i = min; i <= max; i++) {
      840 +                if (dt_print_packed(dtp, fp, data[i], total) < 0)
      841 +                        return (-1);
      842 +        }
      843 +
      844 +        if (dt_printf(dtp, fp, ": %*lld | %lld\n",
      845 +            -dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
      846 +                return (-1);
      847 +
      848 +        return (0);
      849 +}
      850 +
      851 +int
 603  852  dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 604  853      size_t size, uint64_t normal)
 605  854  {
 606  855          const int64_t *data = addr;
 607  856          int i, first_bin, last_bin, base;
 608  857          uint64_t arg;
 609  858          long double total = 0;
 610  859          uint16_t step, levels;
 611  860          char positives = 0, negatives = 0;
 612  861  
↓ open down ↓ 26 lines elided ↑ open up ↑
 639  888                  while (last_bin > 0 && data[last_bin] == 0)
 640  889                          last_bin--;
 641  890  
 642  891                  if (last_bin < levels + 1)
 643  892                          last_bin++;
 644  893          }
 645  894  
 646  895          for (i = first_bin; i <= last_bin; i++) {
 647  896                  positives |= (data[i] > 0);
 648  897                  negatives |= (data[i] < 0);
 649      -                total += dt_fabsl((long double)data[i]);
      898 +                dt_quantize_total(dtp, data[i], &total);
 650  899          }
 651  900  
 652  901          if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
 653  902              "------------- Distribution -------------", "count") < 0)
 654  903                  return (-1);
 655  904  
 656  905          for (i = first_bin; i <= last_bin; i++) {
 657  906                  char c[32];
 658  907                  int err;
 659  908  
 660  909                  if (i == 0) {
 661      -                        (void) snprintf(c, sizeof (c), "< %d",
 662      -                            base / (uint32_t)normal);
      910 +                        (void) snprintf(c, sizeof (c), "< %d", base);
 663  911                          err = dt_printf(dtp, fp, "%16s ", c);
 664  912                  } else if (i == levels + 1) {
 665  913                          (void) snprintf(c, sizeof (c), ">= %d",
 666  914                              base + (levels * step));
 667  915                          err = dt_printf(dtp, fp, "%16s ", c);
 668  916                  } else {
 669  917                          err = dt_printf(dtp, fp, "%16d ",
 670  918                              base + (i - 1) * step);
 671  919                  }
 672  920  
 673  921                  if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal,
 674  922                      total, positives, negatives) < 0)
 675  923                          return (-1);
 676  924          }
 677  925  
 678  926          return (0);
 679  927  }
 680  928  
      929 +/*ARGSUSED*/
      930 +int
      931 +dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
      932 +    size_t size, const dtrace_aggdata_t *aggdata)
      933 +{
      934 +        const int64_t *data = addr;
      935 +        long double total = 0, count = 0;
      936 +        int min, max, base, err;
      937 +        uint64_t arg;
      938 +        uint16_t step, levels;
      939 +        char c[32];
      940 +        unsigned int i;
      941 +
      942 +        if (size < sizeof (uint64_t))
      943 +                return (dt_set_errno(dtp, EDT_DMISMATCH));
      944 +
      945 +        arg = *data++;
      946 +        size -= sizeof (uint64_t);
      947 +
      948 +        base = DTRACE_LQUANTIZE_BASE(arg);
      949 +        step = DTRACE_LQUANTIZE_STEP(arg);
      950 +        levels = DTRACE_LQUANTIZE_LEVELS(arg);
      951 +
      952 +        if (size != sizeof (uint64_t) * (levels + 2))
      953 +                return (dt_set_errno(dtp, EDT_DMISMATCH));
      954 +
      955 +        min = 0;
      956 +        max = levels + 1;
      957 +
      958 +        if (min == 0) {
      959 +                (void) snprintf(c, sizeof (c), "< %d", base);
      960 +                err = dt_printf(dtp, fp, "%8s :", c);
      961 +        } else {
      962 +                err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
      963 +        }
      964 +
      965 +        if (err < 0)
      966 +                return (-1);
      967 +
      968 +        for (i = min; i <= max; i++) {
      969 +                dt_quantize_total(dtp, data[i], &total);
      970 +                count += data[i];
      971 +        }
      972 +
      973 +        for (i = min; i <= max; i++) {
      974 +                if (dt_print_packed(dtp, fp, data[i], total) < 0)
      975 +                        return (-1);
      976 +        }
      977 +
      978 +        (void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
      979 +        return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
      980 +}
      981 +
 681  982  int
 682  983  dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 683  984      size_t size, uint64_t normal)
 684  985  {
 685  986          int i, first_bin, last_bin, bin = 1, order, levels;
 686  987          uint16_t factor, low, high, nsteps;
 687  988          const int64_t *data = addr;
 688  989          int64_t value = 1, next, step;
 689  990          char positives = 0, negatives = 0;
 690  991          long double total = 0;
↓ open down ↓ 37 lines elided ↑ open up ↑
 728 1029                  while (last_bin > 0 && data[last_bin] == 0)
 729 1030                          last_bin--;
 730 1031  
 731 1032                  if (last_bin < levels - 1)
 732 1033                          last_bin++;
 733 1034          }
 734 1035  
 735 1036          for (i = first_bin; i <= last_bin; i++) {
 736 1037                  positives |= (data[i] > 0);
 737 1038                  negatives |= (data[i] < 0);
 738      -                total += dt_fabsl((long double)data[i]);
     1039 +                dt_quantize_total(dtp, data[i], &total);
 739 1040          }
 740 1041  
 741 1042          if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
 742 1043              "------------- Distribution -------------", "count") < 0)
 743 1044                  return (-1);
 744 1045  
 745 1046          for (order = 0; order < low; order++)
 746 1047                  value *= factor;
 747 1048  
 748 1049          next = value * factor;
↓ open down ↓ 62 lines elided ↑ open up ↑
 811 1112      size_t size, uint64_t normal)
 812 1113  {
 813 1114          /* LINTED - alignment */
 814 1115          uint64_t *data = (uint64_t *)addr;
 815 1116  
 816 1117          return (dt_printf(dtp, fp, " %16llu", data[0] ?
 817 1118              (unsigned long long) dt_stddev(data, normal) : 0));
 818 1119  }
 819 1120  
 820 1121  /*ARGSUSED*/
 821      -int
     1122 +static int
 822 1123  dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
 823 1124      size_t nbytes, int width, int quiet, int forceraw)
 824 1125  {
 825 1126          /*
 826 1127           * If the byte stream is a series of printable characters, followed by
 827 1128           * a terminating byte, we print it out as a string.  Otherwise, we
 828 1129           * assume that it's something else and just print the bytes.
 829 1130           */
 830 1131          int i, j, margin = 5;
 831 1132          char *c = (char *)addr;
↓ open down ↓ 32 lines elided ↑ open up ↑
 864 1165                           * a string, and we'll print out the individual bytes.
 865 1166                           */
 866 1167                          for (j = i + 1; j < nbytes; j++) {
 867 1168                                  if (c[j] != '\0')
 868 1169                                          break;
 869 1170                          }
 870 1171  
 871 1172                          if (j != nbytes)
 872 1173                                  break;
 873 1174  
 874      -                        if (quiet)
     1175 +                        if (quiet) {
 875 1176                                  return (dt_printf(dtp, fp, "%s", c));
 876      -                        else
 877      -                                return (dt_printf(dtp, fp, "  %-*s", width, c));
     1177 +                        } else {
     1178 +                                return (dt_printf(dtp, fp, " %s%*s",
     1179 +                                    width < 0 ? " " : "", width, c));
     1180 +                        }
 878 1181                  }
 879 1182  
 880 1183                  break;
 881 1184          }
 882 1185  
 883 1186          if (i == nbytes) {
 884 1187                  /*
 885 1188                   * The byte range is all printable characters, but there is
 886 1189                   * no trailing nul byte.  We'll assume that it's a string and
 887 1190                   * print it as such.
↓ open down ↓ 584 lines elided ↑ open up ↑
1472 1775          assert(remaining >= 0);
1473 1776          trunc.dttd_remaining = remaining;
1474 1777  
1475 1778          (void) func(dtp, dt_trunc_agg, &trunc);
1476 1779  
1477 1780          return (0);
1478 1781  }
1479 1782  
1480 1783  static int
1481 1784  dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
1482      -    caddr_t addr, size_t size, uint64_t normal)
     1785 +    caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
     1786 +    uint64_t normal, dt_print_aggdata_t *pd)
1483 1787  {
1484      -        int err;
     1788 +        int err, width;
1485 1789          dtrace_actkind_t act = rec->dtrd_action;
     1790 +        boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
     1791 +        dtrace_aggdesc_t *agg = aggdata->dtada_desc;
     1792 +
     1793 +        static struct {
     1794 +                size_t size;
     1795 +                int width;
     1796 +                int packedwidth;
     1797 +        } *fmt, fmttab[] = {
     1798 +                { sizeof (uint8_t),     3,      3 },
     1799 +                { sizeof (uint16_t),    5,      5 },
     1800 +                { sizeof (uint32_t),    8,      8 },
     1801 +                { sizeof (uint64_t),    16,     16 },
     1802 +                { 0,                    -50,    16 }
     1803 +        };
     1804 +
     1805 +        if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
     1806 +                dtrace_recdesc_t *r;
     1807 +
     1808 +                width = 0;
     1809 +
     1810 +                /*
     1811 +                 * To print our quantization header for either an agghist or
     1812 +                 * aggpack aggregation, we need to iterate through all of our
     1813 +                 * of our records to determine their width.
     1814 +                 */
     1815 +                for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
     1816 +                        for (fmt = fmttab; fmt->size &&
     1817 +                            fmt->size != r->dtrd_size; fmt++)
     1818 +                                continue;
     1819 +
     1820 +                        width += fmt->packedwidth + 1;
     1821 +                }
     1822 +
     1823 +                if (pd->dtpa_agghist) {
     1824 +                        if (dt_print_quanthdr(dtp, fp, width) < 0)
     1825 +                                return (-1);
     1826 +                } else {
     1827 +                        if (dt_print_quanthdr_packed(dtp, fp,
     1828 +                            width, aggdata, r->dtrd_action) < 0)
     1829 +                                return (-1);
     1830 +                }
     1831 +
     1832 +                pd->dtpa_agghisthdr = agg->dtagd_varid;
     1833 +        }
     1834 +
     1835 +        if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
     1836 +                char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
     1837 +                char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
     1838 +                int64_t val;
     1839 +
     1840 +                assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
     1841 +                val = (long long)*((uint64_t *)addr);
     1842 +
     1843 +                if (dt_printf(dtp, fp, " ") < 0)
     1844 +                        return (-1);
     1845 +
     1846 +                return (dt_print_quantline(dtp, fp, val, normal,
     1847 +                    aggdata->dtada_total, positives, negatives));
     1848 +        }
     1849 +
     1850 +        if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
     1851 +                switch (act) {
     1852 +                case DTRACEAGG_QUANTIZE:
     1853 +                        return (dt_print_quantize_packed(dtp,
     1854 +                            fp, addr, size, aggdata));
     1855 +                case DTRACEAGG_LQUANTIZE:
     1856 +                        return (dt_print_lquantize_packed(dtp,
     1857 +                            fp, addr, size, aggdata));
     1858 +                default:
     1859 +                        break;
     1860 +                }
     1861 +        }
1486 1862  
1487 1863          switch (act) {
1488 1864          case DTRACEACT_STACK:
1489 1865                  return (dt_print_stack(dtp, fp, NULL, addr,
1490 1866                      rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
1491 1867  
1492 1868          case DTRACEACT_USTACK:
1493 1869          case DTRACEACT_JSTACK:
1494 1870                  return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg));
1495 1871  
↓ open down ↓ 22 lines elided ↑ open up ↑
1518 1894          case DTRACEAGG_AVG:
1519 1895                  return (dt_print_average(dtp, fp, addr, size, normal));
1520 1896  
1521 1897          case DTRACEAGG_STDDEV:
1522 1898                  return (dt_print_stddev(dtp, fp, addr, size, normal));
1523 1899  
1524 1900          default:
1525 1901                  break;
1526 1902          }
1527 1903  
     1904 +        for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
     1905 +                continue;
     1906 +
     1907 +        width = packed ? fmt->packedwidth : fmt->width;
     1908 +
1528 1909          switch (size) {
1529 1910          case sizeof (uint64_t):
1530      -                err = dt_printf(dtp, fp, " %16lld",
     1911 +                err = dt_printf(dtp, fp, " %*lld", width,
1531 1912                      /* LINTED - alignment */
1532 1913                      (long long)*((uint64_t *)addr) / normal);
1533 1914                  break;
1534 1915          case sizeof (uint32_t):
1535 1916                  /* LINTED - alignment */
1536      -                err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) /
     1917 +                err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
1537 1918                      (uint32_t)normal);
1538 1919                  break;
1539 1920          case sizeof (uint16_t):
1540 1921                  /* LINTED - alignment */
1541      -                err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) /
     1922 +                err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
1542 1923                      (uint32_t)normal);
1543 1924                  break;
1544 1925          case sizeof (uint8_t):
1545      -                err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) /
     1926 +                err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
1546 1927                      (uint32_t)normal);
1547 1928                  break;
1548 1929          default:
1549      -                err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
     1930 +                err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
1550 1931                  break;
1551 1932          }
1552 1933  
1553 1934          return (err);
1554 1935  }
1555 1936  
1556 1937  int
1557 1938  dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
1558 1939  {
1559 1940          int i, aggact = 0;
1560 1941          dt_print_aggdata_t *pd = arg;
1561 1942          const dtrace_aggdata_t *aggdata = aggsdata[0];
1562 1943          dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1563 1944          FILE *fp = pd->dtpa_fp;
1564 1945          dtrace_hdl_t *dtp = pd->dtpa_dtp;
1565 1946          dtrace_recdesc_t *rec;
1566 1947          dtrace_actkind_t act;
1567 1948          caddr_t addr;
1568 1949          size_t size;
1569 1950  
     1951 +        pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
     1952 +        pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
     1953 +
1570 1954          /*
1571 1955           * Iterate over each record description in the key, printing the traced
1572 1956           * data, skipping the first datum (the tuple member created by the
1573 1957           * compiler).
1574 1958           */
1575 1959          for (i = 1; i < agg->dtagd_nrecs; i++) {
1576 1960                  rec = &agg->dtagd_rec[i];
1577 1961                  act = rec->dtrd_action;
1578 1962                  addr = aggdata->dtada_data + rec->dtrd_offset;
1579 1963                  size = rec->dtrd_size;
1580 1964  
1581 1965                  if (DTRACEACT_ISAGG(act)) {
1582 1966                          aggact = i;
1583 1967                          break;
1584 1968                  }
1585 1969  
1586      -                if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0)
     1970 +                if (dt_print_datum(dtp, fp, rec, addr,
     1971 +                    size, aggdata, 1, pd) < 0)
1587 1972                          return (-1);
1588 1973  
1589 1974                  if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1590 1975                      DTRACE_BUFDATA_AGGKEY) < 0)
1591 1976                          return (-1);
1592 1977          }
1593 1978  
1594 1979          assert(aggact != 0);
1595 1980  
1596 1981          for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
↓ open down ↓ 2 lines elided ↑ open up ↑
1599 1984                  aggdata = aggsdata[i];
1600 1985                  agg = aggdata->dtada_desc;
1601 1986                  rec = &agg->dtagd_rec[aggact];
1602 1987                  act = rec->dtrd_action;
1603 1988                  addr = aggdata->dtada_data + rec->dtrd_offset;
1604 1989                  size = rec->dtrd_size;
1605 1990  
1606 1991                  assert(DTRACEACT_ISAGG(act));
1607 1992                  normal = aggdata->dtada_normal;
1608 1993  
1609      -                if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0)
     1994 +                if (dt_print_datum(dtp, fp, rec, addr,
     1995 +                    size, aggdata, normal, pd) < 0)
1610 1996                          return (-1);
1611 1997  
1612 1998                  if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1613 1999                      DTRACE_BUFDATA_AGGVAL) < 0)
1614 2000                          return (-1);
1615 2001  
1616 2002                  if (!pd->dtpa_allunprint)
1617 2003                          agg->dtagd_flags |= DTRACE_AGD_PRINTED;
1618 2004          }
1619 2005  
1620      -        if (dt_printf(dtp, fp, "\n") < 0)
1621      -                return (-1);
     2006 +        if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
     2007 +                if (dt_printf(dtp, fp, "\n") < 0)
     2008 +                        return (-1);
     2009 +        }
1622 2010  
1623 2011          if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
1624 2012              DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
1625 2013                  return (-1);
1626 2014  
1627 2015          return (0);
1628 2016  }
1629 2017  
1630 2018  int
1631 2019  dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg)
↓ open down ↓ 436 lines elided ↑ open up ↑
2068 2456                                  goto nextrec;
2069 2457                          }
2070 2458  
2071 2459                          if (act == DTRACEACT_TRACEMEM) {
2072 2460                                  if (tracememsize == 0 ||
2073 2461                                      tracememsize > rec->dtrd_size) {
2074 2462                                          tracememsize = rec->dtrd_size;
2075 2463                                  }
2076 2464  
2077 2465                                  n = dt_print_bytes(dtp, fp, addr,
2078      -                                    tracememsize, 33, quiet, 1);
     2466 +                                    tracememsize, -33, quiet, 1);
2079 2467  
2080 2468                                  tracememsize = 0;
2081 2469  
2082 2470                                  if (n < 0)
2083 2471                                          return (-1);
2084 2472  
2085 2473                                  goto nextrec;
2086 2474                          }
2087 2475  
2088 2476                          switch (rec->dtrd_size) {
↓ open down ↓ 12 lines elided ↑ open up ↑
2101 2489                                  n = dt_printf(dtp, fp, quiet ? "%d" : " %5d",
2102 2490                                      /* LINTED - alignment */
2103 2491                                      *((uint16_t *)addr));
2104 2492                                  break;
2105 2493                          case sizeof (uint8_t):
2106 2494                                  n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
2107 2495                                      *((uint8_t *)addr));
2108 2496                                  break;
2109 2497                          default:
2110 2498                                  n = dt_print_bytes(dtp, fp, addr,
2111      -                                    rec->dtrd_size, 33, quiet, 0);
     2499 +                                    rec->dtrd_size, -33, quiet, 0);
2112 2500                                  break;
2113 2501                          }
2114 2502  
2115 2503                          if (n < 0)
2116 2504                                  return (-1); /* errno is set for us */
2117 2505  
2118 2506  nextrec:
2119 2507                          if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0)
2120 2508                                  return (-1); /* errno is set for us */
2121 2509                  }
↓ open down ↓ 543 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX