diff options
Diffstat (limited to 'usr/src/lib/libdtrace/common/dt_aggregate.c')
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_aggregate.c | 89 |
1 files changed, 88 insertions, 1 deletions
diff --git a/usr/src/lib/libdtrace/common/dt_aggregate.c b/usr/src/lib/libdtrace/common/dt_aggregate.c index 2e66250b88..bb766f71c4 100644 --- a/usr/src/lib/libdtrace/common/dt_aggregate.c +++ b/usr/src/lib/libdtrace/common/dt_aggregate.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2011, Joyent, Inc. All rights reserved. + */ #include <stdlib.h> #include <strings.h> @@ -204,6 +206,83 @@ dt_aggregate_lquantizedcmp(int64_t *lhs, int64_t *rhs) return (0); } +static void +dt_aggregate_llquantize(int64_t *existing, int64_t *new, size_t size) +{ + int i; + + for (i = 1; i < size / sizeof (int64_t); i++) + existing[i] = existing[i] + new[i]; +} + +static long double +dt_aggregate_llquantizedsum(int64_t *llquanta) +{ + int64_t arg = *llquanta++; + uint16_t factor = DTRACE_LLQUANTIZE_FACTOR(arg); + uint16_t low = DTRACE_LLQUANTIZE_LOW(arg); + uint16_t high = DTRACE_LLQUANTIZE_HIGH(arg); + uint16_t nsteps = DTRACE_LLQUANTIZE_NSTEP(arg); + int bin = 0, order; + int64_t value = 1, next, step; + long double total; + + assert(nsteps >= factor); + assert(nsteps % factor == 0); + + for (order = 0; order < low; order++) + value *= factor; + + total = (long double)llquanta[bin++] * (long double)(value - 1); + + next = value * factor; + step = next > nsteps ? next / nsteps : 1; + + while (order <= high) { + assert(value < next); + total += (long double)llquanta[bin++] * (long double)(value); + + if ((value += step) != next) + continue; + + next = value * factor; + step = next > nsteps ? next / nsteps : 1; + order++; + } + + return (total + (long double)llquanta[bin] * (long double)value); +} + +static int +dt_aggregate_llquantizedcmp(int64_t *lhs, int64_t *rhs) +{ + long double lsum = dt_aggregate_llquantizedsum(lhs); + long double rsum = dt_aggregate_llquantizedsum(rhs); + int64_t lzero, rzero; + + if (lsum < rsum) + return (DT_LESSTHAN); + + if (lsum > rsum) + return (DT_GREATERTHAN); + + /* + * If they're both equal, then we will compare based on the weights at + * zero. If the weights at zero are equal, then this will be judged a + * tie and will be resolved based on the key comparison. + */ + lzero = lhs[1]; + rzero = rhs[1]; + + if (lzero < rzero) + return (DT_LESSTHAN); + + if (lzero > rzero) + return (DT_GREATERTHAN); + + return (0); +} + static int dt_aggregate_quantizedcmp(int64_t *lhs, int64_t *rhs) { @@ -582,6 +661,10 @@ hashnext: h->dtahe_aggregate = dt_aggregate_lquantize; break; + case DTRACEAGG_LLQUANTIZE: + h->dtahe_aggregate = dt_aggregate_llquantize; + break; + case DTRACEAGG_COUNT: case DTRACEAGG_SUM: case DTRACEAGG_AVG: @@ -849,6 +932,10 @@ dt_aggregate_valcmp(const void *lhs, const void *rhs) rval = dt_aggregate_lquantizedcmp(laddr, raddr); break; + case DTRACEAGG_LLQUANTIZE: + rval = dt_aggregate_llquantizedcmp(laddr, raddr); + break; + case DTRACEAGG_COUNT: case DTRACEAGG_SUM: case DTRACEAGG_MIN: |