From: Martin Sperl Date: Tue, 6 May 2014 21:37:47 +0000 (+0000) Subject: added interpolation for percentile X-Git-Tag: v1.5.0-rc1~106^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F465%2Fhead;p=thirdparty%2Frrdtool-1.x.git added interpolation for percentile --- diff --git a/doc/rrdgraph_rpn.pod b/doc/rrdgraph_rpn.pod index 80b427b9..fd1f3099 100644 --- a/doc/rrdgraph_rpn.pod +++ b/doc/rrdgraph_rpn.pod @@ -253,6 +253,22 @@ This also allows for extrapolation into the future (say a few days) - you may need to define the data series whit the optional start= parameter, so that the source data series has enough data to provide prediction also at the beginning of a graph... +The percentile can be between [-100:+100]. +The positive percentiles interpolates between values while the negative will take the closest. + +Example: you run 7 shifts with a window of 1800seconds. Assuming that the rrd-file +has a step size of 300 seconds this means we have to do the percentile calculation +based on a max of 42 distinct values (less if you got NAN). that means that in the +best case you get a step rate between values of 2.4 percent. +so if you ask for the 99th percentile, then you would need to look at the 41.59th +value. As we only have integers, either the 41st or the 42nd value. + +With the positive percentile a linear interpolation between the 2 values is done +to get the effective value. + +The negative returns the closest value distance wise - so in the above case 42nd value, +which is effectively returning the Percentile100 or the max of the previous 7 days in the window. + Here an example, that will create a 10 day graph that also shows the prediction 3 days into the future with its uncertainty value (as defined by avg+-4*sigma) This also shows if the prediction is exceeded at a certain point. diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index 80522717..1796e47b 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -855,7 +855,7 @@ short rpn_calc( if (rpnp[rpi].op == OP_PREDICTPERC) { stackunderflow(1); percentile = rpnstack->s[--stptr]; - if ((percentile<0) || (percentile > 100)) { + if (abs(percentile) > 100) { rrd_set_error("unsupported percentile: %f",percentile); return -1; } @@ -957,11 +957,19 @@ short rpn_calc( /* sort the numbers */ qsort(extra,count,sizeof(double),rpn_compare_double); /* get the percentile selected */ - int idx=(int)round(percentile * ((float)count-1.0)); - /* maybe we should also do an interpolation between the 2 - * neighboring fields, similar to what we do with MEDIAN - */ - val = extra[idx]; + double idxf = percentile * ((float)count-1.0); + if (percentile < 0) { /* take the next best */ + int idx = round(abs(idxf)); + val = extra[idx]; + } else { /* interpolate */ + int idx = floor(idxf); + double deltax = idxf - idx; + val = extra[idx]; + if (deltax) { /* this check also handles the percentile=100 case */ + double deltay = extra[idx + 1] - extra[idx]; + val += deltay * deltax; + } + } } break; default: /* should not get here ... */