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_aggregate.c
          +++ new/usr/src/lib/libdtrace/common/dt_aggregate.c
↓ open down ↓ 17 lines elided ↑ open up ↑
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  /*
  28      - * Copyright (c) 2011, Joyent, Inc. All rights reserved.
       28 + * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  29   29   * Copyright (c) 2012 by Delphix. All rights reserved.
  30   30   */
  31   31  
  32   32  #include <stdlib.h>
  33   33  #include <strings.h>
  34   34  #include <errno.h>
  35   35  #include <unistd.h>
  36   36  #include <dt_impl.h>
  37   37  #include <assert.h>
  38   38  #include <alloca.h>
↓ open down ↓ 1245 lines elided ↑ open up ↑
1284 1284                  next = h->dtahe_nextall;
1285 1285  
1286 1286                  if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1)
1287 1287                          return (-1);
1288 1288          }
1289 1289  
1290 1290          return (0);
1291 1291  }
1292 1292  
1293 1293  static int
     1294 +dt_aggregate_total(dtrace_hdl_t *dtp, boolean_t clear)
     1295 +{
     1296 +        dt_ahashent_t *h;
     1297 +        dtrace_aggdata_t **total;
     1298 +        dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
     1299 +        dt_aggregate_t *agp = &dtp->dt_aggregate;
     1300 +        dt_ahash_t *hash = &agp->dtat_hash;
     1301 +        uint32_t tflags;
     1302 +
     1303 +        tflags = DTRACE_A_TOTAL | DTRACE_A_HASNEGATIVES | DTRACE_A_HASPOSITIVES;
     1304 +
     1305 +        /*
     1306 +         * If we need to deliver per-aggregation totals, we're going to take
     1307 +         * three passes over the aggregate:  one to clear everything out and
     1308 +         * determine our maximum aggregation ID, one to actually total
     1309 +         * everything up, and a final pass to assign the totals to the
     1310 +         * individual elements.
     1311 +         */
     1312 +        for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
     1313 +                dtrace_aggdata_t *aggdata = &h->dtahe_data;
     1314 +
     1315 +                if ((id = dt_aggregate_aggvarid(h)) > max)
     1316 +                        max = id;
     1317 +
     1318 +                aggdata->dtada_total = 0;
     1319 +                aggdata->dtada_flags &= ~tflags;
     1320 +        }
     1321 +
     1322 +        if (clear || max == DTRACE_AGGVARIDNONE)
     1323 +                return (0);
     1324 +
     1325 +        total = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
     1326 +
     1327 +        if (total == NULL)
     1328 +                return (-1);
     1329 +
     1330 +        for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
     1331 +                dtrace_aggdata_t *aggdata = &h->dtahe_data;
     1332 +                dtrace_aggdesc_t *agg = aggdata->dtada_desc;
     1333 +                dtrace_recdesc_t *rec;
     1334 +                caddr_t data;
     1335 +                int64_t val, *addr;
     1336 +
     1337 +                rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
     1338 +                data = aggdata->dtada_data;
     1339 +                addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
     1340 +
     1341 +                switch (rec->dtrd_action) {
     1342 +                case DTRACEAGG_STDDEV:
     1343 +                        val = dt_stddev((uint64_t *)addr, 1);
     1344 +                        break;
     1345 +
     1346 +                case DTRACEAGG_SUM:
     1347 +                case DTRACEAGG_COUNT:
     1348 +                        val = *addr;
     1349 +                        break;
     1350 +
     1351 +                case DTRACEAGG_AVG:
     1352 +                        val = addr[0] ? (addr[1] / addr[0]) : 0;
     1353 +                        break;
     1354 +
     1355 +                default:
     1356 +                        continue;
     1357 +                }
     1358 +
     1359 +                if (total[agg->dtagd_varid] == NULL) {
     1360 +                        total[agg->dtagd_varid] = aggdata;
     1361 +                        aggdata->dtada_flags |= DTRACE_A_TOTAL;
     1362 +                } else {
     1363 +                        aggdata = total[agg->dtagd_varid];
     1364 +                }
     1365 +
     1366 +                if (val > 0)
     1367 +                        aggdata->dtada_flags |= DTRACE_A_HASPOSITIVES;
     1368 +
     1369 +                if (val < 0) {
     1370 +                        aggdata->dtada_flags |= DTRACE_A_HASNEGATIVES;
     1371 +                        val = -val;
     1372 +                }
     1373 +
     1374 +                if (dtp->dt_options[DTRACEOPT_AGGZOOM] != DTRACEOPT_UNSET) {
     1375 +                        val = (int64_t)((long double)val *
     1376 +                            (1 / DTRACE_AGGZOOM_MAX));
     1377 +
     1378 +                        if (val > aggdata->dtada_total)
     1379 +                                aggdata->dtada_total = val;
     1380 +                } else {
     1381 +                        aggdata->dtada_total += val;
     1382 +                }
     1383 +        }
     1384 +
     1385 +        /*
     1386 +         * And now one final pass to set everyone's total.
     1387 +         */
     1388 +        for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
     1389 +                dtrace_aggdata_t *aggdata = &h->dtahe_data, *t;
     1390 +                dtrace_aggdesc_t *agg = aggdata->dtada_desc;
     1391 +
     1392 +                if ((t = total[agg->dtagd_varid]) == NULL || aggdata == t)
     1393 +                        continue;
     1394 +
     1395 +                aggdata->dtada_total = t->dtada_total;
     1396 +                aggdata->dtada_flags |= (t->dtada_flags & tflags);
     1397 +        }
     1398 +
     1399 +        dt_free(dtp, total);
     1400 +
     1401 +        return (0);
     1402 +}
     1403 +
     1404 +static int
     1405 +dt_aggregate_minmaxbin(dtrace_hdl_t *dtp, boolean_t clear)
     1406 +{
     1407 +        dt_ahashent_t *h;
     1408 +        dtrace_aggdata_t **minmax;
     1409 +        dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
     1410 +        dt_aggregate_t *agp = &dtp->dt_aggregate;
     1411 +        dt_ahash_t *hash = &agp->dtat_hash;
     1412 +
     1413 +        for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
     1414 +                dtrace_aggdata_t *aggdata = &h->dtahe_data;
     1415 +
     1416 +                if ((id = dt_aggregate_aggvarid(h)) > max)
     1417 +                        max = id;
     1418 +
     1419 +                aggdata->dtada_minbin = 0;
     1420 +                aggdata->dtada_maxbin = 0;
     1421 +                aggdata->dtada_flags &= ~DTRACE_A_MINMAXBIN;
     1422 +        }
     1423 +
     1424 +        if (clear || max == DTRACE_AGGVARIDNONE)
     1425 +                return (0);
     1426 +
     1427 +        minmax = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
     1428 +
     1429 +        if (minmax == NULL)
     1430 +                return (-1);
     1431 +
     1432 +        for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
     1433 +                dtrace_aggdata_t *aggdata = &h->dtahe_data;
     1434 +                dtrace_aggdesc_t *agg = aggdata->dtada_desc;
     1435 +                dtrace_recdesc_t *rec;
     1436 +                caddr_t data;
     1437 +                int64_t *addr;
     1438 +                int minbin = -1, maxbin = -1, i;
     1439 +                int start = 0, size;
     1440 +
     1441 +                rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
     1442 +                size = rec->dtrd_size / sizeof (int64_t);
     1443 +                data = aggdata->dtada_data;
     1444 +                addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
     1445 +
     1446 +                switch (rec->dtrd_action) {
     1447 +                case DTRACEAGG_LQUANTIZE:
     1448 +                        /*
     1449 +                         * For lquantize(), we always display the entire range
     1450 +                         * of the aggregation when aggpack is set.
     1451 +                         */
     1452 +                        start = 1;
     1453 +                        minbin = start;
     1454 +                        maxbin = size - 1 - start;
     1455 +                        break;
     1456 +
     1457 +                case DTRACEAGG_QUANTIZE:
     1458 +                        for (i = start; i < size; i++) {
     1459 +                                if (!addr[i])
     1460 +                                        continue;
     1461 +
     1462 +                                if (minbin == -1)
     1463 +                                        minbin = i - start;
     1464 +
     1465 +                                maxbin = i - start;
     1466 +                        }
     1467 +
     1468 +                        if (minbin == -1) {
     1469 +                                /*
     1470 +                                 * If we have no data (e.g., due to a clear()
     1471 +                                 * or negative increments), we'll use the
     1472 +                                 * zero bucket as both our min and max.
     1473 +                                 */
     1474 +                                minbin = maxbin = DTRACE_QUANTIZE_ZEROBUCKET;
     1475 +                        }
     1476 +
     1477 +                        break;
     1478 +
     1479 +                default:
     1480 +                        continue;
     1481 +                }
     1482 +
     1483 +                if (minmax[agg->dtagd_varid] == NULL) {
     1484 +                        minmax[agg->dtagd_varid] = aggdata;
     1485 +                        aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
     1486 +                        aggdata->dtada_minbin = minbin;
     1487 +                        aggdata->dtada_maxbin = maxbin;
     1488 +                        continue;
     1489 +                }
     1490 +
     1491 +                if (minbin < minmax[agg->dtagd_varid]->dtada_minbin)
     1492 +                        minmax[agg->dtagd_varid]->dtada_minbin = minbin;
     1493 +
     1494 +                if (maxbin > minmax[agg->dtagd_varid]->dtada_maxbin)
     1495 +                        minmax[agg->dtagd_varid]->dtada_maxbin = maxbin;
     1496 +        }
     1497 +
     1498 +        /*
     1499 +         * And now one final pass to set everyone's minbin and maxbin.
     1500 +         */
     1501 +        for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
     1502 +                dtrace_aggdata_t *aggdata = &h->dtahe_data, *mm;
     1503 +                dtrace_aggdesc_t *agg = aggdata->dtada_desc;
     1504 +
     1505 +                if ((mm = minmax[agg->dtagd_varid]) == NULL || aggdata == mm)
     1506 +                        continue;
     1507 +
     1508 +                aggdata->dtada_minbin = mm->dtada_minbin;
     1509 +                aggdata->dtada_maxbin = mm->dtada_maxbin;
     1510 +                aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
     1511 +        }
     1512 +
     1513 +        dt_free(dtp, minmax);
     1514 +
     1515 +        return (0);
     1516 +}
     1517 +
     1518 +static int
1294 1519  dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
1295 1520      dtrace_aggregate_f *func, void *arg,
1296 1521      int (*sfunc)(const void *, const void *))
1297 1522  {
1298 1523          dt_aggregate_t *agp = &dtp->dt_aggregate;
1299 1524          dt_ahashent_t *h, **sorted;
1300 1525          dt_ahash_t *hash = &agp->dtat_hash;
1301 1526          size_t i, nentries = 0;
     1527 +        int rval = -1;
     1528 +
     1529 +        agp->dtat_flags &= ~(DTRACE_A_TOTAL | DTRACE_A_MINMAXBIN);
     1530 +
     1531 +        if (dtp->dt_options[DTRACEOPT_AGGHIST] != DTRACEOPT_UNSET) {
     1532 +                agp->dtat_flags |= DTRACE_A_TOTAL;
     1533 +
     1534 +                if (dt_aggregate_total(dtp, B_FALSE) != 0)
     1535 +                        return (-1);
     1536 +        }
     1537 +
     1538 +        if (dtp->dt_options[DTRACEOPT_AGGPACK] != DTRACEOPT_UNSET) {
     1539 +                agp->dtat_flags |= DTRACE_A_MINMAXBIN;
     1540 +
     1541 +                if (dt_aggregate_minmaxbin(dtp, B_FALSE) != 0)
     1542 +                        return (-1);
     1543 +        }
1302 1544  
1303 1545          for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall)
1304 1546                  nentries++;
1305 1547  
1306 1548          sorted = dt_alloc(dtp, nentries * sizeof (dt_ahashent_t *));
1307 1549  
1308 1550          if (sorted == NULL)
1309      -                return (-1);
     1551 +                goto out;
1310 1552  
1311 1553          for (h = hash->dtah_all, i = 0; h != NULL; h = h->dtahe_nextall)
1312 1554                  sorted[i++] = h;
1313 1555  
1314 1556          (void) pthread_mutex_lock(&dt_qsort_lock);
1315 1557  
1316 1558          if (sfunc == NULL) {
1317 1559                  dt_aggregate_qsort(dtp, sorted, nentries,
1318 1560                      sizeof (dt_ahashent_t *), NULL);
1319 1561          } else {
↓ open down ↓ 3 lines elided ↑ open up ↑
1323 1565                   * "aggsortkey" and "aggsortkeypos" options.
1324 1566                   */
1325 1567                  qsort(sorted, nentries, sizeof (dt_ahashent_t *), sfunc);
1326 1568          }
1327 1569  
1328 1570          (void) pthread_mutex_unlock(&dt_qsort_lock);
1329 1571  
1330 1572          for (i = 0; i < nentries; i++) {
1331 1573                  h = sorted[i];
1332 1574  
1333      -                if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1) {
1334      -                        dt_free(dtp, sorted);
1335      -                        return (-1);
1336      -                }
     1575 +                if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1)
     1576 +                        goto out;
1337 1577          }
1338 1578  
     1579 +        rval = 0;
     1580 +out:
     1581 +        if (agp->dtat_flags & DTRACE_A_TOTAL)
     1582 +                (void) dt_aggregate_total(dtp, B_TRUE);
     1583 +
     1584 +        if (agp->dtat_flags & DTRACE_A_MINMAXBIN)
     1585 +                (void) dt_aggregate_minmaxbin(dtp, B_TRUE);
     1586 +
1339 1587          dt_free(dtp, sorted);
1340      -        return (0);
     1588 +        return (rval);
1341 1589  }
1342 1590  
1343 1591  int
1344 1592  dtrace_aggregate_walk_sorted(dtrace_hdl_t *dtp,
1345 1593      dtrace_aggregate_f *func, void *arg)
1346 1594  {
1347 1595          return (dt_aggregate_walk_sorted(dtp, func, arg, NULL));
1348 1596  }
1349 1597  
1350 1598  int
↓ open down ↓ 502 lines elided ↑ open up ↑
1853 2101  
1854 2102          return (rval);
1855 2103  }
1856 2104  
1857 2105  int
1858 2106  dtrace_aggregate_print(dtrace_hdl_t *dtp, FILE *fp,
1859 2107      dtrace_aggregate_walk_f *func)
1860 2108  {
1861 2109          dt_print_aggdata_t pd;
1862 2110  
     2111 +        bzero(&pd, sizeof (pd));
     2112 +
1863 2113          pd.dtpa_dtp = dtp;
1864 2114          pd.dtpa_fp = fp;
1865 2115          pd.dtpa_allunprint = 1;
1866 2116  
1867 2117          if (func == NULL)
1868 2118                  func = dtrace_aggregate_walk_sorted;
1869 2119  
1870 2120          if ((*func)(dtp, dt_print_agg, &pd) == -1)
1871 2121                  return (dt_set_errno(dtp, dtp->dt_errno));
1872 2122  
↓ open down ↓ 66 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX