add safety check against NaN or Infinity results in composite value

Add step-like filtering functions based on sigmoid shapes
Add prototype for p99ms cutoff in value function
This commit is contained in:
Jonathan Shook 2023-11-02 14:41:14 -05:00
parent be80d35ae8
commit 082c72afe0
4 changed files with 41 additions and 40 deletions

View File

@ -37,6 +37,9 @@ public class FrameSampleSet extends ArrayList<FrameSample> {
double product = 1.0;
for (FrameSample sample : this) {
double weighted = sample.weightedValue();
if (Double.isNaN(weighted)||Double.isInfinite(weighted)) {
throw new RuntimeException("Not a real value for '" + sample.criterion().name() + "': " + weighted);
}
product *= weighted;
}
return product;

View File

@ -32,6 +32,7 @@ import io.nosqlbench.scenarios.simframe.capture.SimFrameCapture;
import io.nosqlbench.scenarios.simframe.capture.SimFrameJournal;
import io.nosqlbench.scenarios.simframe.findmax.SC_findmax;
import io.nosqlbench.scenarios.simframe.planning.SimFrameFunction;
import io.nosqlbench.scenarios.simframe.stabilization.StatFunctions;
import org.apache.commons.math4.legacy.exception.MathIllegalStateException;
import org.apache.commons.math4.legacy.optim.*;
import org.apache.commons.math4.legacy.optim.nonlinear.scalar.GoalType;
@ -177,6 +178,8 @@ public class SC_optimo extends SCBaseScenario {
SimFrameCapture sampler = new SimFrameCapture();
NBMetricTimer result_timer = activity.find().timer("name:result");
NBMetricTimer latency_histo = result_timer.attachHdrDeltaHistogram();
NBMetricTimer result_success_timer = activity.find().timer("name:result_success");
NBMetricGauge cyclerate_gauge = activity.find().gauge("name=config_cyclerate");
NBMetricHistogram tries_histo_src = activity.find().histogram("name=tries");
@ -200,8 +203,12 @@ public class SC_optimo extends SCBaseScenario {
double triesP99 = tries_histo.getDeltaSnapshot(90).get99thPercentile();
return 1/triesP99;
});
sampler.addDirect("latency_cutoff_50", () -> {
double latencyP99 = latency_histo.getDeltaSnapshot(90).getP99ms();
double v = StatFunctions.sigmoidE4LowPass(latencyP99, 50);
// System.out.println("v:"+v+" p99ms:" + latencyP99);
return v;
},1.0d);
return sampler;
}
}

View File

@ -108,12 +108,12 @@ public class StabilityDetector implements Runnable {
basis *= reductionFactor;
}
double time = ((double)(nextCheckAt - startedAt))/1000d;
System.out.printf("% 4.1fS STABILITY %g :", time, basis);
for (int i = 0; i < stddev.length; i++) {
System.out.printf("[%d]: %g ", windows[i], stddev[i]);
}
System.out.println();
// double time = ((double)(nextCheckAt - startedAt))/1000d;
// System.out.printf("% 4.1fS STABILITY %g :", time, basis);
// for (int i = 0; i < stddev.length; i++) {
// System.out.printf("[%d]: %g ", windows[i], stddev[i]);
// }
// System.out.println();
return basis;
}

View File

@ -21,36 +21,27 @@ import java.util.ListIterator;
import java.util.function.ToDoubleFunction;
public class StatFunctions {
// public static double[] lastStddev(int[] ranges, LinkedList<TimedSample> values) {
// double[] avgs = new double[ranges.length];
// for (int i = 0; i < ranges.length; i++) {
// int range = ranges[i];
// if (values.size()>=range) {
// double avg=0.0d;
// ListIterator<TimedSample> iter = listIterator(size() - range);
// while (iter.hasNext()) avg += (iter.next().value / range);
// avgs[i]=avg;
// } else {
// avgs[i]=Double.NaN;
// }
// }
//
// }
//
// public static double[] stackedSample(LinkedList<TimedSample> values, ToDoubleFunction<double[]> func, int... windows) {
// double[] results = new double[windows.length];
// for (int i = 0; i < windows.length; i++) {
// int range = windows[i];
// if (values.size()>=range) {
// double avg=0.0d;
// ListIterator<TimedSample> iter = listIterator(size() - range);
// while (iter.hasNext()) avg += (iter.next().value / range);
// results[i]=avg;
// } else {
// results[i]=Double.NaN;
// }
// }
//
//
// }
/**
* A continuous sigmoid function which looks very close to a step function at the inflection points.
* This provides a navigable surface for optimizers while also acting like an all-or none filter.
* This function yields 0.0d or 1.0d over most of its domain, except between shelf-0.0025 and shelf,
* where it is a steep sigmoid. Specifically, at shelf, the value is 1.0; at shelf-0.0001, the value is 0.9999,
* dropping quickly on the lower side of shelf, leveling out at 0.0 at shelf-0.0025.
* @param input x
* @param lowcut The point on the x axis at which all higher values should yield 1.0
*/
public static double sigmoidE4HighPass(double input, double lowcut) {
return 1.0d/(1.0d+Math.pow(Math.E,(-10000.0d*(input-(lowcut-0.001d)))));
}
/**
* Like {@link #sigmoidE4HighPass, but inverted with respect to the Y axis. This has the same roll-off charater
* where the high (1.0) shelf in included through the cutoff value.
* @param input x
* @param lowcut The point on the x axis at which all lower values should yield 1.0
*/
public static double sigmoidE4LowPass(double input, double highcut) {
double v = 1.0d/(1.0d + Math.pow(Math.E, (10000.0d * (input - (highcut + 0.001d)))));
return v;
}
}