Print this page
4471 DTrace count() with histogram
4472 DTrace full width distribution histograms
4473 DTrace frequency trails
        
*** 22,32 ****
   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
  
  /*
!  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
   * Copyright (c) 2012 by Delphix. All rights reserved.
   */
  
  #include <stdlib.h>
  #include <strings.h>
--- 22,32 ----
   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
  
  /*
!  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
   * Copyright (c) 2012 by Delphix. All rights reserved.
   */
  
  #include <stdlib.h>
  #include <strings.h>
*** 52,61 ****
--- 52,80 ----
                  return (-x);
  
          return (x);
  }
  
+ static int
+ dt_ndigits(long long val)
+ {
+         int rval = 1;
+         long long cmp = 10;
+ 
+         if (val < 0) {
+                 val = val == INT64_MIN ? INT64_MAX : -val;
+                 rval++;
+         }
+ 
+         while (val > cmp && cmp > 0) {
+                 rval++;
+                 cmp *= 10;
+         }
+ 
+         return (rval < 4 ? 4 : rval);
+ }
+ 
  /*
   * 128-bit arithmetic functions needed to support the stddev() aggregating
   * action.
   */
  static int
*** 480,490 ****
  dt_nullrec()
  {
          return (DTRACE_CONSUME_NEXT);
  }
  
! int
  dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
      uint64_t normal, long double total, char positives, char negatives)
  {
          long double f;
          uint_t depth, len = 40;
--- 499,627 ----
  dt_nullrec()
  {
          return (DTRACE_CONSUME_NEXT);
  }
  
! static void
! dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
! {
!         long double val = dt_fabsl((long double)datum);
! 
!         if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
!                 *total += val;
!                 return;
!         }
! 
!         /*
!          * If we're zooming in on an aggregation, we want the height of the
!          * highest value to be approximately 95% of total bar height -- so we
!          * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
!          * our highest value.
!          */
!         val *= 1 / DTRACE_AGGZOOM_MAX;
! 
!         if (*total < val)
!                 *total = val;
! }
! 
! static int
! dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
! {
!         return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
!             width ? width : 16, width ? "key" : "value",
!             "------------- Distribution -------------", "count"));
! }
! 
! static int
! dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
!     const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
! {
!         int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
!         int minwidth, maxwidth, i;
! 
!         assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
! 
!         if (action == DTRACEAGG_QUANTIZE) {
!                 if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
!                         min--;
! 
!                 if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
!                         max++;
! 
!                 minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
!                 maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
!         } else {
!                 maxwidth = 8;
!                 minwidth = maxwidth - 1;
!                 max++;
!         }
! 
!         if (dt_printf(dtp, fp, "\n%*s %*s .",
!             width, width > 0 ? "key" : "", minwidth, "min") < 0)
!                 return (-1);
! 
!         for (i = min; i <= max; i++) {
!                 if (dt_printf(dtp, fp, "-") < 0)
!                         return (-1);
!         }
! 
!         return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
! }
! 
! /*
!  * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
!  * inclusive) to represent aggregations via UTF-8 -- which are expressed via
!  * 3-byte UTF-8 sequences.
!  */
! #define DTRACE_AGGUTF8_FULL     0x2588
! #define DTRACE_AGGUTF8_BASE     0x258f
! #define DTRACE_AGGUTF8_LEVELS   8
! 
! #define DTRACE_AGGUTF8_BYTE0(val)       (0xe0 | ((val) >> 12))
! #define DTRACE_AGGUTF8_BYTE1(val)       (0x80 | (((val) >> 6) & 0x3f))
! #define DTRACE_AGGUTF8_BYTE2(val)       (0x80 | ((val) & 0x3f))
! 
! static int
! dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
!     uint64_t normal, long double total)
! {
!         uint_t len = 40, i, whole, partial;
!         long double f = (dt_fabsl((long double)val) * len) / total;
!         const char *spaces = "                                        ";
! 
!         whole = (uint_t)f;
!         partial = (uint_t)((f - (long double)(uint_t)f) *
!             (long double)DTRACE_AGGUTF8_LEVELS);
! 
!         if (dt_printf(dtp, fp, "|") < 0)
!                 return (-1);
! 
!         for (i = 0; i < whole; i++) {
!                 if (dt_printf(dtp, fp, "%c%c%c",
!                     DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
!                     DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
!                     DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
!                         return (-1);
!         }
! 
!         if (partial != 0) {
!                 partial = DTRACE_AGGUTF8_BASE - (partial - 1);
! 
!                 if (dt_printf(dtp, fp, "%c%c%c",
!                     DTRACE_AGGUTF8_BYTE0(partial),
!                     DTRACE_AGGUTF8_BYTE1(partial),
!                     DTRACE_AGGUTF8_BYTE2(partial)) < 0)
!                         return (-1);
! 
!                 i++;
!         }
! 
!         return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
!             (long long)val / normal));
! }
! 
! static int
  dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
      uint64_t normal, long double total, char positives, char negatives)
  {
          long double f;
          uint_t depth, len = 40;
*** 498,507 ****
--- 635,649 ----
          assert(!(val > 0 && !positives));
          assert(!(val != 0 && total == 0));
  
          if (!negatives) {
                  if (positives) {
+                         if (dtp->dt_encoding == DT_ENCODING_UTF8) {
+                                 return (dt_print_quantline_utf8(dtp, fp, val,
+                                     normal, total));
+                         }
+ 
                          f = (dt_fabsl((long double)val) * len) / total;
                          depth = (uint_t)(f + 0.5);
                  } else {
                          depth = 0;
                  }
*** 540,549 ****
--- 682,757 ----
                      ats + len - depth, spaces + depth,
                      (long long)val / normal));
          }
  }
  
+ /*
+  * As with UTF-8 printing of aggregations, we use a subset of the Unicode
+  * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
+  * aggregation.
+  */
+ #define DTRACE_AGGPACK_BASE     0x2581
+ #define DTRACE_AGGPACK_LEVELS   8
+ 
+ static int
+ dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
+     long double datum, long double total)
+ {
+         static boolean_t utf8_checked = B_FALSE;
+         static boolean_t utf8;
+         char *ascii = "__xxxxXX";
+         char *neg = "vvvvVV";
+         unsigned int len;
+         long double val;
+ 
+         if (!utf8_checked) {
+                 char *term;
+ 
+                 /*
+                  * We want to determine if we can reasonably emit UTF-8 for our
+                  * packed aggregation.  To do this, we will check for terminals
+                  * that are known to be primitive to emit UTF-8 on these.
+                  */
+                 utf8_checked = B_TRUE;
+ 
+                 if (dtp->dt_encoding == DT_ENCODING_ASCII)
+                         utf8 = B_FALSE;
+                 else if (dtp->dt_encoding == DT_ENCODING_UTF8)
+                         utf8 = B_TRUE;
+                 else if ((term = getenv("TERM")) != NULL &&
+                     (strcmp(term, "sun") == 0 ||
+                     strcmp(term, "sun-color") == 0) ||
+                     strcmp(term, "dumb") == 0)
+                         utf8 = B_FALSE;
+                 else
+                         utf8 = B_TRUE;
+         }
+ 
+         if (datum == 0)
+                 return (dt_printf(dtp, fp, " "));
+ 
+         if (datum < 0) {
+                 len = strlen(neg);
+                 val = dt_fabsl(datum * (len - 1)) / total;
+                 return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
+         }
+ 
+         if (utf8) {
+                 int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
+                     (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
+ 
+                 return (dt_printf(dtp, fp, "%c%c%c",
+                     DTRACE_AGGUTF8_BYTE0(block),
+                     DTRACE_AGGUTF8_BYTE1(block),
+                     DTRACE_AGGUTF8_BYTE2(block)));
+         }
+ 
+         len = strlen(ascii);
+         val = (datum * (len - 1)) / total;
+         return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
+ }
+ 
  int
  dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
      size_t size, uint64_t normal)
  {
          const int64_t *data = addr;
*** 557,569 ****
          while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
                  first_bin++;
  
          if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
                  /*
!                  * There isn't any data.  This is possible if (and only if)
!                  * negative increment values have been used.  In this case,
!                  * we'll print the buckets around 0.
                   */
                  first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
                  last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
          } else {
                  if (first_bin > 0)
--- 765,777 ----
          while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
                  first_bin++;
  
          if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
                  /*
!                  * There isn't any data.  This is possible if the aggregation
!                  * has been clear()'d or if negative increment values have been
!                  * used.  Regardless, we'll print the buckets around 0.
                   */
                  first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
                  last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
          } else {
                  if (first_bin > 0)
*** 577,591 ****
          }
  
          for (i = first_bin; i <= last_bin; i++) {
                  positives |= (data[i] > 0);
                  negatives |= (data[i] < 0);
!                 total += dt_fabsl((long double)data[i]);
          }
  
!         if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
!             "------------- Distribution -------------", "count") < 0)
                  return (-1);
  
          for (i = first_bin; i <= last_bin; i++) {
                  if (dt_printf(dtp, fp, "%16lld ",
                      (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
--- 785,798 ----
          }
  
          for (i = first_bin; i <= last_bin; i++) {
                  positives |= (data[i] > 0);
                  negatives |= (data[i] < 0);
!                 dt_quantize_total(dtp, data[i], &total);
          }
  
!         if (dt_print_quanthdr(dtp, fp, 0) < 0)
                  return (-1);
  
          for (i = first_bin; i <= last_bin; i++) {
                  if (dt_printf(dtp, fp, "%16lld ",
                      (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
*** 598,607 ****
--- 805,856 ----
  
          return (0);
  }
  
  int
+ dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+     size_t size, const dtrace_aggdata_t *aggdata)
+ {
+         const int64_t *data = addr;
+         long double total = 0, count = 0;
+         int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
+         int64_t minval, maxval;
+ 
+         if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
+                 return (dt_set_errno(dtp, EDT_DMISMATCH));
+ 
+         if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
+                 min--;
+ 
+         if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
+                 max++;
+ 
+         minval = DTRACE_QUANTIZE_BUCKETVAL(min);
+         maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
+ 
+         if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
+             (long long)minval) < 0)
+                 return (-1);
+ 
+         for (i = min; i <= max; i++) {
+                 dt_quantize_total(dtp, data[i], &total);
+                 count += data[i];
+         }
+ 
+         for (i = min; i <= max; i++) {
+                 if (dt_print_packed(dtp, fp, data[i], total) < 0)
+                         return (-1);
+         }
+ 
+         if (dt_printf(dtp, fp, ": %*lld | %lld\n",
+             -dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
+                 return (-1);
+ 
+         return (0);
+ }
+ 
+ int
  dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
      size_t size, uint64_t normal)
  {
          const int64_t *data = addr;
          int i, first_bin, last_bin, base;
*** 644,654 ****
          }
  
          for (i = first_bin; i <= last_bin; i++) {
                  positives |= (data[i] > 0);
                  negatives |= (data[i] < 0);
!                 total += dt_fabsl((long double)data[i]);
          }
  
          if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
              "------------- Distribution -------------", "count") < 0)
                  return (-1);
--- 893,903 ----
          }
  
          for (i = first_bin; i <= last_bin; i++) {
                  positives |= (data[i] > 0);
                  negatives |= (data[i] < 0);
!                 dt_quantize_total(dtp, data[i], &total);
          }
  
          if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
              "------------- Distribution -------------", "count") < 0)
                  return (-1);
*** 656,667 ****
          for (i = first_bin; i <= last_bin; i++) {
                  char c[32];
                  int err;
  
                  if (i == 0) {
!                         (void) snprintf(c, sizeof (c), "< %d",
!                             base / (uint32_t)normal);
                          err = dt_printf(dtp, fp, "%16s ", c);
                  } else if (i == levels + 1) {
                          (void) snprintf(c, sizeof (c), ">= %d",
                              base + (levels * step));
                          err = dt_printf(dtp, fp, "%16s ", c);
--- 905,915 ----
          for (i = first_bin; i <= last_bin; i++) {
                  char c[32];
                  int err;
  
                  if (i == 0) {
!                         (void) snprintf(c, sizeof (c), "< %d", base);
                          err = dt_printf(dtp, fp, "%16s ", c);
                  } else if (i == levels + 1) {
                          (void) snprintf(c, sizeof (c), ">= %d",
                              base + (levels * step));
                          err = dt_printf(dtp, fp, "%16s ", c);
*** 676,685 ****
--- 924,986 ----
          }
  
          return (0);
  }
  
+ /*ARGSUSED*/
+ int
+ dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+     size_t size, const dtrace_aggdata_t *aggdata)
+ {
+         const int64_t *data = addr;
+         long double total = 0, count = 0;
+         int min, max, base, err;
+         uint64_t arg;
+         uint16_t step, levels;
+         char c[32];
+         unsigned int i;
+ 
+         if (size < sizeof (uint64_t))
+                 return (dt_set_errno(dtp, EDT_DMISMATCH));
+ 
+         arg = *data++;
+         size -= sizeof (uint64_t);
+ 
+         base = DTRACE_LQUANTIZE_BASE(arg);
+         step = DTRACE_LQUANTIZE_STEP(arg);
+         levels = DTRACE_LQUANTIZE_LEVELS(arg);
+ 
+         if (size != sizeof (uint64_t) * (levels + 2))
+                 return (dt_set_errno(dtp, EDT_DMISMATCH));
+ 
+         min = 0;
+         max = levels + 1;
+ 
+         if (min == 0) {
+                 (void) snprintf(c, sizeof (c), "< %d", base);
+                 err = dt_printf(dtp, fp, "%8s :", c);
+         } else {
+                 err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
+         }
+ 
+         if (err < 0)
+                 return (-1);
+ 
+         for (i = min; i <= max; i++) {
+                 dt_quantize_total(dtp, data[i], &total);
+                 count += data[i];
+         }
+ 
+         for (i = min; i <= max; i++) {
+                 if (dt_print_packed(dtp, fp, data[i], total) < 0)
+                         return (-1);
+         }
+ 
+         (void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
+         return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
+ }
+ 
  int
  dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
      size_t size, uint64_t normal)
  {
          int i, first_bin, last_bin, bin = 1, order, levels;
*** 733,743 ****
          }
  
          for (i = first_bin; i <= last_bin; i++) {
                  positives |= (data[i] > 0);
                  negatives |= (data[i] < 0);
!                 total += dt_fabsl((long double)data[i]);
          }
  
          if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
              "------------- Distribution -------------", "count") < 0)
                  return (-1);
--- 1034,1044 ----
          }
  
          for (i = first_bin; i <= last_bin; i++) {
                  positives |= (data[i] > 0);
                  negatives |= (data[i] < 0);
!                 dt_quantize_total(dtp, data[i], &total);
          }
  
          if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
              "------------- Distribution -------------", "count") < 0)
                  return (-1);
*** 816,826 ****
          return (dt_printf(dtp, fp, " %16llu", data[0] ?
              (unsigned long long) dt_stddev(data, normal) : 0));
  }
  
  /*ARGSUSED*/
! int
  dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
      size_t nbytes, int width, int quiet, int forceraw)
  {
          /*
           * If the byte stream is a series of printable characters, followed by
--- 1117,1127 ----
          return (dt_printf(dtp, fp, " %16llu", data[0] ?
              (unsigned long long) dt_stddev(data, normal) : 0));
  }
  
  /*ARGSUSED*/
! static int
  dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
      size_t nbytes, int width, int quiet, int forceraw)
  {
          /*
           * If the byte stream is a series of printable characters, followed by
*** 869,882 ****
                          }
  
                          if (j != nbytes)
                                  break;
  
!                         if (quiet)
                                  return (dt_printf(dtp, fp, "%s", c));
!                         else
!                                 return (dt_printf(dtp, fp, "  %-*s", width, c));
                  }
  
                  break;
          }
  
--- 1170,1185 ----
                          }
  
                          if (j != nbytes)
                                  break;
  
!                         if (quiet) {
                                  return (dt_printf(dtp, fp, "%s", c));
!                         } else {
!                                 return (dt_printf(dtp, fp, " %s%*s",
!                                     width < 0 ? " " : "", width, c));
!                         }
                  }
  
                  break;
          }
  
*** 1477,1490 ****
          return (0);
  }
  
  static int
  dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
!     caddr_t addr, size_t size, uint64_t normal)
  {
!         int err;
          dtrace_actkind_t act = rec->dtrd_action;
  
          switch (act) {
          case DTRACEACT_STACK:
                  return (dt_print_stack(dtp, fp, NULL, addr,
                      rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
--- 1780,1866 ----
          return (0);
  }
  
  static int
  dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
!     caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
!     uint64_t normal, dt_print_aggdata_t *pd)
  {
!         int err, width;
          dtrace_actkind_t act = rec->dtrd_action;
+         boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
+         dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ 
+         static struct {
+                 size_t size;
+                 int width;
+                 int packedwidth;
+         } *fmt, fmttab[] = {
+                 { sizeof (uint8_t),     3,      3 },
+                 { sizeof (uint16_t),    5,      5 },
+                 { sizeof (uint32_t),    8,      8 },
+                 { sizeof (uint64_t),    16,     16 },
+                 { 0,                    -50,    16 }
+         };
+ 
+         if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
+                 dtrace_recdesc_t *r;
+ 
+                 width = 0;
+ 
+                 /*
+                  * To print our quantization header for either an agghist or
+                  * aggpack aggregation, we need to iterate through all of our
+                  * of our records to determine their width.
+                  */
+                 for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
+                         for (fmt = fmttab; fmt->size &&
+                             fmt->size != r->dtrd_size; fmt++)
+                                 continue;
+ 
+                         width += fmt->packedwidth + 1;
+                 }
+ 
+                 if (pd->dtpa_agghist) {
+                         if (dt_print_quanthdr(dtp, fp, width) < 0)
+                                 return (-1);
+                 } else {
+                         if (dt_print_quanthdr_packed(dtp, fp,
+                             width, aggdata, r->dtrd_action) < 0)
+                                 return (-1);
+                 }
+ 
+                 pd->dtpa_agghisthdr = agg->dtagd_varid;
+         }
+ 
+         if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
+                 char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
+                 char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
+                 int64_t val;
+ 
+                 assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
+                 val = (long long)*((uint64_t *)addr);
+ 
+                 if (dt_printf(dtp, fp, " ") < 0)
+                         return (-1);
+ 
+                 return (dt_print_quantline(dtp, fp, val, normal,
+                     aggdata->dtada_total, positives, negatives));
+         }
+ 
+         if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
+                 switch (act) {
+                 case DTRACEAGG_QUANTIZE:
+                         return (dt_print_quantize_packed(dtp,
+                             fp, addr, size, aggdata));
+                 case DTRACEAGG_LQUANTIZE:
+                         return (dt_print_lquantize_packed(dtp,
+                             fp, addr, size, aggdata));
+                 default:
+                         break;
+                 }
+         }
  
          switch (act) {
          case DTRACEACT_STACK:
                  return (dt_print_stack(dtp, fp, NULL, addr,
                      rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
*** 1523,1554 ****
  
          default:
                  break;
          }
  
          switch (size) {
          case sizeof (uint64_t):
!                 err = dt_printf(dtp, fp, " %16lld",
                      /* LINTED - alignment */
                      (long long)*((uint64_t *)addr) / normal);
                  break;
          case sizeof (uint32_t):
                  /* LINTED - alignment */
!                 err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) /
                      (uint32_t)normal);
                  break;
          case sizeof (uint16_t):
                  /* LINTED - alignment */
!                 err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) /
                      (uint32_t)normal);
                  break;
          case sizeof (uint8_t):
!                 err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) /
                      (uint32_t)normal);
                  break;
          default:
!                 err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
                  break;
          }
  
          return (err);
  }
--- 1899,1935 ----
  
          default:
                  break;
          }
  
+         for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
+                 continue;
+ 
+         width = packed ? fmt->packedwidth : fmt->width;
+ 
          switch (size) {
          case sizeof (uint64_t):
!                 err = dt_printf(dtp, fp, " %*lld", width,
                      /* LINTED - alignment */
                      (long long)*((uint64_t *)addr) / normal);
                  break;
          case sizeof (uint32_t):
                  /* LINTED - alignment */
!                 err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
                      (uint32_t)normal);
                  break;
          case sizeof (uint16_t):
                  /* LINTED - alignment */
!                 err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
                      (uint32_t)normal);
                  break;
          case sizeof (uint8_t):
!                 err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
                      (uint32_t)normal);
                  break;
          default:
!                 err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
                  break;
          }
  
          return (err);
  }
*** 1565,1574 ****
--- 1946,1958 ----
          dtrace_recdesc_t *rec;
          dtrace_actkind_t act;
          caddr_t addr;
          size_t size;
  
+         pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
+         pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
+ 
          /*
           * Iterate over each record description in the key, printing the traced
           * data, skipping the first datum (the tuple member created by the
           * compiler).
           */
*** 1581,1591 ****
                  if (DTRACEACT_ISAGG(act)) {
                          aggact = i;
                          break;
                  }
  
!                 if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0)
                          return (-1);
  
                  if (dt_buffered_flush(dtp, NULL, rec, aggdata,
                      DTRACE_BUFDATA_AGGKEY) < 0)
                          return (-1);
--- 1965,1976 ----
                  if (DTRACEACT_ISAGG(act)) {
                          aggact = i;
                          break;
                  }
  
!                 if (dt_print_datum(dtp, fp, rec, addr,
!                     size, aggdata, 1, pd) < 0)
                          return (-1);
  
                  if (dt_buffered_flush(dtp, NULL, rec, aggdata,
                      DTRACE_BUFDATA_AGGKEY) < 0)
                          return (-1);
*** 1604,1626 ****
                  size = rec->dtrd_size;
  
                  assert(DTRACEACT_ISAGG(act));
                  normal = aggdata->dtada_normal;
  
!                 if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0)
                          return (-1);
  
                  if (dt_buffered_flush(dtp, NULL, rec, aggdata,
                      DTRACE_BUFDATA_AGGVAL) < 0)
                          return (-1);
  
                  if (!pd->dtpa_allunprint)
                          agg->dtagd_flags |= DTRACE_AGD_PRINTED;
          }
  
          if (dt_printf(dtp, fp, "\n") < 0)
                  return (-1);
  
          if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
              DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
                  return (-1);
  
--- 1989,2014 ----
                  size = rec->dtrd_size;
  
                  assert(DTRACEACT_ISAGG(act));
                  normal = aggdata->dtada_normal;
  
!                 if (dt_print_datum(dtp, fp, rec, addr,
!                     size, aggdata, normal, pd) < 0)
                          return (-1);
  
                  if (dt_buffered_flush(dtp, NULL, rec, aggdata,
                      DTRACE_BUFDATA_AGGVAL) < 0)
                          return (-1);
  
                  if (!pd->dtpa_allunprint)
                          agg->dtagd_flags |= DTRACE_AGD_PRINTED;
          }
  
+         if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
                  if (dt_printf(dtp, fp, "\n") < 0)
                          return (-1);
+         }
  
          if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
              DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
                  return (-1);
  
*** 2073,2083 ****
                                      tracememsize > rec->dtrd_size) {
                                          tracememsize = rec->dtrd_size;
                                  }
  
                                  n = dt_print_bytes(dtp, fp, addr,
!                                     tracememsize, 33, quiet, 1);
  
                                  tracememsize = 0;
  
                                  if (n < 0)
                                          return (-1);
--- 2461,2471 ----
                                      tracememsize > rec->dtrd_size) {
                                          tracememsize = rec->dtrd_size;
                                  }
  
                                  n = dt_print_bytes(dtp, fp, addr,
!                                     tracememsize, -33, quiet, 1);
  
                                  tracememsize = 0;
  
                                  if (n < 0)
                                          return (-1);
*** 2106,2116 ****
                                  n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
                                      *((uint8_t *)addr));
                                  break;
                          default:
                                  n = dt_print_bytes(dtp, fp, addr,
!                                     rec->dtrd_size, 33, quiet, 0);
                                  break;
                          }
  
                          if (n < 0)
                                  return (-1); /* errno is set for us */
--- 2494,2504 ----
                                  n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
                                      *((uint8_t *)addr));
                                  break;
                          default:
                                  n = dt_print_bytes(dtp, fp, addr,
!                                     rec->dtrd_size, -33, quiet, 0);
                                  break;
                          }
  
                          if (n < 0)
                                  return (-1); /* errno is set for us */