cleanups and minor docs

This commit is contained in:
Jonathan Shook 2023-10-16 00:21:19 -05:00
parent aaf58984d6
commit 921c6e17e3
29 changed files with 937 additions and 103 deletions

View File

@ -35,7 +35,7 @@ public class ProcessInvoker {
/**
* Run the process with a specified timeout and alias.
*
* @param alias the name of the process for logging and result gathering
* @param alias the name of the process for logging and samples gathering
* @param timeoutSeconds the number of seconds to wait for the process to return
* @param cmdline the command line
* @return a ProcessResult

View File

@ -39,7 +39,7 @@ public class ProcessResult {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("--- process result\nstatus:%d", exitStatus));
sb.append(String.format("--- process samples\nstatus:%d", exitStatus));
sb.append(String.format(" time:%.3fs", (durationNanos/1000000000.0)));
sb.append(String.format(" dir:%s",cmdDir));
sb.append("\n--- stdout:\n");

View File

@ -131,8 +131,8 @@ public class WorkloadContainerVerifications {
// try (CqlSession session = CqlSession.builder().addContactPoint(new InetSocketAddress(hostIP, mappedPort9042)).withLocalDatacenter(datacenter).build()) {
// //->Check for the creation of the keyspace baselines
// logger.info("Checking for the creation of the keyspace \"baselines\"...");
// ResultSet result = session.execute("SELECT keyspace_name FROM system_schema.keyspaces");
// List<Row> rows = result.all();
// ResultSet samples = session.execute("SELECT keyspace_name FROM system_schema.keyspaces");
// List<Row> rows = samples.all();
// boolean keyspaceFound = false;
// for (Row row : rows) {
// if (row.getString("keyspace_name").equals("baselines")) {
@ -145,8 +145,8 @@ public class WorkloadContainerVerifications {
//
// //->Check for the creation of the baselines keyvalue table
// logger.info("Checking for the creation of the table \"baselines.keyvalue\"...");
// result = session.execute("SELECT table_name FROM system_schema.tables WHERE keyspace_name='baselines'");
// rows = result.all();
// samples = session.execute("SELECT table_name FROM system_schema.tables WHERE keyspace_name='baselines'");
// rows = samples.all();
// boolean tableFound = false;
// for (Row row : rows) {
// if (row.getString("table_name").equals("keyvalue")) {

View File

@ -147,7 +147,7 @@ public class DirectRuntimeScenarioTests {
public void test_SC_extension_example() {
NBScenario scenario = new SC_extension_example(testC,"test_SC_extension_example");
ScenarioResult result = scenario.apply(NBSceneBuffer.traced(scenario));
// result.exitWithCode();
// samples.exitWithCode();
assertThat(result.getIOLog()).contains("3+5=8");
}
@Disabled("enable before merge")

View File

@ -44,16 +44,16 @@ public class SC_optimo_test extends SCBaseScenario {
* var a = 0.0 + values.pa;
* var b = 0.0 + values.pb;
*
* var result = 1000000 - ((Math.abs(100 - a) + Math.abs(100 - b)));
* print("a=" + a + ",b=" + b + ", r=" + result);
* return result;
* var samples = 1000000 - ((Math.abs(100 - a) + Math.abs(100 - b)));
* print("a=" + a + ",b=" + b + ", r=" + samples);
* return samples;
* }
* );
*
* var result = optimo.optimize();
* var samples = optimo.optimize();
*
* print("optimized result was " + result);
* print("map of result was " + result.getMap());
* print("optimized samples was " + samples);
* print("map of samples was " + samples.getMap());
* }</pre>
*/
@Override
@ -72,7 +72,7 @@ public class SC_optimo_test extends SCBaseScenario {
};
bobby.setObjectiveFunction(f);
MVResult result = bobby.optimize();
stdout.println("optimized result was " + result);
stdout.println("map of result was " + result.getMap());
stdout.println("optimized samples was " + result);
stdout.println("map of samples was " + result.getMap());
}
}

View File

@ -129,7 +129,7 @@ public class ScriptExampleTests {
ScenarioResult scenarioResult = runScenario("optimo");
String iolog = scenarioResult.getIOLog();
System.out.println("iolog\n" + iolog);
assertThat(iolog).contains("map of result was");
assertThat(iolog).contains("map of samples was");
}
@Disabled

View File

@ -81,7 +81,7 @@ public class SC_optimo extends SCBaseScenario {
/**
* <P>This function is the objective function, and is responsible for applying
* the parameters and yielding a result. The higher the returned result, the
* the parameters and yielding a samples. The higher the returned samples, the
* better the parameters are.</P>
* <P>The parameter values will be passed in as an array, pair-wise with the param calls above.</P>
*/
@ -148,12 +148,12 @@ public class SC_optimo extends SCBaseScenario {
MVResult result = bobby.optimize();
controller.stop(flywheel);
stdout.println("optimized result was " + result);
stdout.println("map of result was " + result.getMap());
stdout.println("optimized samples was " + result);
stdout.println("map of samples was " + result.getMap());
// TODO: controller startAt should not return the activity itself, but a control point, like activityDef
// TODO: warn user if one of the result params is near or at the range allowed, as there
// could be a better result if the range is arbitrarily limiting the parameter space.
// TODO: warn user if one of the samples params is near or at the range allowed, as there
// could be a better samples if the range is arbitrarily limiting the parameter space.
}
}

View File

@ -18,7 +18,10 @@ package io.nosqlbench.scenarios.findmax;
import java.util.Arrays;
public class DoubleMap {
/**
* Provide named doubles without resorting to Map and boxing shenanigans.
*/
public class BasisValues {
private double[] values = new double[0];
private String[] names = new String[0];

View File

@ -19,10 +19,21 @@ package io.nosqlbench.scenarios.findmax;
import java.util.function.DoubleSupplier;
import java.util.function.ToDoubleFunction;
/**
* A criterion is a single component factor of a value for a black-box testing samples.
*
* @param name name of the factor
* @param evaltype Whether to compute the basis value as a deltaV/deltaT,
* a raw value, or a functional remix of the other values.
* @param remix A remix function, required for {@link EvalType#remix}
* @param supplier A value supplier, required for {@link EvalType#direct} and {@link EvalType#deltaT}
* @param weight A weight which affects how the basis value is applied as a factor to composite value. Set this to NaN to nullify effects.
* @param frameStartCallback A runnable which can be used to do preparatory work at the start of sampling a simulation frame
*/
public record Criterion(
String name,
EvalType evaltype,
ToDoubleFunction<DoubleMap> remix,
ToDoubleFunction<BasisValues> remix,
DoubleSupplier supplier,
double weight,
/**

View File

@ -17,7 +17,18 @@
package io.nosqlbench.scenarios.findmax;
public enum EvalType {
/**
* A basis value is read from a supplier directly at the end of a simulation frame with no additional computation.
*/
direct,
/**
* At the beginning of a simulation frame, starting basis values and starting frame times are recorded. At the end
* of that simulation frame, ending basis values and ending time are record. The basis value is computed as
* ΔV/ΔT.
*/
deltaT,
/**
* At the end of a simulation frame, any remix values are computed as a function over any previous defined basis values.
*/
remix
}

View File

@ -18,6 +18,10 @@ package io.nosqlbench.scenarios.findmax;
import io.nosqlbench.engine.core.lifecycle.scenario.context.ScenarioParams;
/**
* These search parameters are based on the original findmax algorithm, and
* should be reduced down to the minimum set needed.
*/
public record FindmaxSearchParams(
int sample_time_ms,
int sample_max,

View File

@ -16,6 +16,9 @@
package io.nosqlbench.scenarios.findmax;
/**
* A frame sample is responsible for capturing the data associated with a criterion.
*/
public record FrameSample(
Criterion criterion,
int index,
@ -23,22 +26,22 @@ public record FrameSample(
long endAt,
double startval,
double endval,
double calculated,
DoubleMap vars
double basis,
BasisValues vars
) {
public FrameSample {
vars.put(criterion.name(), calculated);
vars.put(criterion.name(), basis);
}
public double weightedValue() {
if (Double.isNaN(criterion.weight())) {
return 1.0d;
} else {
return calculated * criterion().weight();
return basis * criterion().weight();
}
}
private double calculatedValue() {
private double calculateBasis() {
return switch (criterion.evaltype()) {
case direct -> endval;
case deltaT -> (endval - startval) / seconds();
@ -50,7 +53,7 @@ public record FrameSample(
return ((double) (endAt - startAt)) / 1000d;
}
public static FrameSample init(Criterion criterion, int index, DoubleMap vars) {
public static FrameSample init(Criterion criterion, int index, BasisValues vars) {
return new FrameSample(criterion, index, 0, 0, Double.NaN, Double.NaN, Double.NaN, vars);
}
@ -67,8 +70,11 @@ public record FrameSample(
return complete;
}
/**
* Take a frame sample which is fully populated with measured values and convert it into one with a computed basis value.
*/
private FrameSample tally() {
return new FrameSample(criterion, index, startAt, endAt, startval, endval, calculatedValue(), vars);
return new FrameSample(criterion, index, startAt, endAt, startval, endval, calculateBasis(), vars);
}
@Override
@ -80,13 +86,13 @@ public record FrameSample(
index,
// seconds(),
// deltaV(),
calculated,
basis,
weightedValue(),
(Double.isNaN(criterion.weight()) ? " [NEUTRAL WEIGHT]" : "")
);
}
private double deltaV() {
return endval - startval;
}
// private double deltaV() {
// return endval - startval;
// }
}

View File

@ -19,6 +19,9 @@ package io.nosqlbench.scenarios.findmax;
import java.util.ArrayList;
import java.util.List;
/**
* A bundle of frame samples
*/
public class FrameSampleSet extends ArrayList<FrameSample> {
public FrameSampleSet(List<FrameSample> samples) {
super(samples);

View File

@ -18,12 +18,14 @@ package io.nosqlbench.scenarios.findmax;
import java.util.List;
/**
* Provide an observer-only view of a simulation journal
*/
public interface JournalView {
List<SimFrame> frames();
SimFrame last();
SimFrame beforeLast();
SimFrame bestRun();
SimFrame before(SimFrame frame);
SimFrame after(SimFrame frame);
}

View File

@ -31,19 +31,24 @@ import java.util.HashMap;
import java.util.Map;
/**
* <PRE>{@code
* Performing FindMax analysis with the following parameters:
* Scale sample window between %d and %d\n",sample_time_ms,sample_max
* increasing by %.3fX on each rejected iteration.\n", sample_incr
* Set target rate to %d + %d * ( %d ^iter) \n", rate_base, rate_step, rate_incr
* for each iteration accepted in a row.\n"
* Schedule %s operations at a time per thread.\n", min_stride
* Report the average result of running the findmax search algorithm %d times.\n",averageof
* Reject iterations which fail to achieve %2.0f%% of the target rate.\n", testrate_cutoff * 100
* Reject iterations which fail to achieve %2.0f%% of the best rate.\n", bestrate_cutoff * 100
* Reject iterations which fail to achieve better than %dms response\n", latency_cutoff
* at percentile p%f\n", latency_pctile * 100
* }</PRE>
* <P>This is the Java-native version of findmax on the NB5.21 architecture. It has been modified from the
* previous form in significant ways.</P>
* <UL>
* <LI>Instead of pass/fail criteria all performance factors are expressed as a value function.
* This will make it easy to adapt different search algorithms (in the form of non-derivative multivariate optimizers)
* to the same approach.</LI>
* <LI>A set of simulation frame utilities bundles the derivation of black-box values. These will be used to refine
* findmax, but will
* be general-purposed for any other analysis and optimization method as needed.
* </LI>
* <LI>The search strategy which determines the parameters for the next simulation frame has been factored out into a
* planner.</LI>
* </UL>
*
* <P>There is an accompanying visual narrative "findmax.png" bundled with this source code to help explain
* the search pattern of findmax. Additional docs and a usage guide will follow.</P>
*
* <P>This can be tested as <PRE>{@code nb5 --show-stacktraces java io.nosqlbench.scenarios.findmax.SC_findmax threads=36}</PRE></P>
*/
public class SC_findmax extends SCBaseScenario {
private final static Logger logger = LogManager.getLogger(SC_findmax.class);
@ -60,7 +65,7 @@ public class SC_findmax extends SCBaseScenario {
Map<String, String> activityParams = new HashMap<>(Map.of(
"cycles", String.valueOf(Long.MAX_VALUE),
"threads", params.getOrDefault("threads","1"),
"threads", params.getOrDefault("threads", "1"),
"driver", "diag",
"rate", String.valueOf(ratespec.opsPerSec),
"dryrun", "op"
@ -80,7 +85,7 @@ public class SC_findmax extends SCBaseScenario {
Activity flywheel = controller.start(activityParams);
SimFrameCapture capture = this.perfValueMeasures(flywheel, 0.99, 50);
SimFrameCapture capture = this.perfValueMeasures(flywheel);
SimFramePlanner planner = new SimFramePlanner(findmaxSettings);
SimFrameJournal journal = new SimFrameJournal();
@ -102,7 +107,7 @@ public class SC_findmax extends SCBaseScenario {
// could be a better result if the range is arbitrarily limiting the parameter space.
}
private SimFrameCapture perfValueMeasures(Activity activity, double fractional_quantile, double cutoff_ms) {
private SimFrameCapture perfValueMeasures(Activity activity) {
SimFrameCapture sampler = new SimFrameCapture();
NBMetricTimer result_timer = activity.find().timer("name:result");
@ -116,12 +121,12 @@ public class SC_findmax extends SCBaseScenario {
sampler.addRemix("achieved_success_ratio", vars -> {
// exponentially penalize results which do not attain 100% successful op rate
double basis = Math.min(1.0d, vars.get("achieved_ok_oprate") / vars.get("achieved_oprate"));
return Math.pow(basis,3);
return Math.pow(basis, 3);
});
sampler.addRemix("achieved_target_ratio", (vars) -> {
// exponentially penalize results which do not attain 100% target rate
double basis = Math.min(1.0d, vars.get("achieved_ok_oprate") / vars.get("target_rate"));
return Math.pow(basis,3);
return Math.pow(basis, 3);
});
// TODO: add response time with a sigmoid style threshold at fractional_quantile and cutoff_ms
@ -152,11 +157,4 @@ public class SC_findmax extends SCBaseScenario {
return sampler;
}
private final static record RunParams(
int sample_seconds,
double target_rate
) {
}
}

View File

@ -17,16 +17,16 @@
package io.nosqlbench.scenarios.findmax;
/**
* Capture the control inputs as well as the result of a sample period of a simulated workload.
* Capture the control inputs as well as the samples of a sample period of a simulated workload.
* @param params The parameters which control the simulated workload during the sample window
* @param result The measured result, including key metrics and criteria for the sample window
* @param samples The measured samples, including key metrics and criteria for the sample window
*/
public record SimFrame(SimFrameParams params, FrameSampleSet result) {
public record SimFrame(SimFrameParams params, FrameSampleSet samples) {
public double value() {
return result().value();
return samples().value();
}
public int index() {
return result.index();
return samples.index();
}

View File

@ -49,7 +49,7 @@ public class SimFrameCapture implements SimFrameResults {
* coefficient of weight for this measure
* @param callback
*/
private void add(String name, EvalType type, ToDoubleFunction<DoubleMap> remix, DoubleSupplier supplier, double weight, Runnable callback) {
private void add(String name, EvalType type, ToDoubleFunction<BasisValues> remix, DoubleSupplier supplier, double weight, Runnable callback) {
this.criteria.add(new Criterion(name, type, remix, supplier, weight, callback==null? () -> {} : callback));
}
@ -98,15 +98,15 @@ public class SimFrameCapture implements SimFrameResults {
* @param remix
* A function which relies on previously computed raw values.
* @param weight
* The weight to apply to the result of this value for the final frame sample value.
* The weight to apply to the samples of this value for the final frame sample value.
* @param callback
* An optional callback to invoke when the frame starts
*/
public void addRemix(String name, ToDoubleFunction<DoubleMap> remix, double weight, Runnable callback) {
public void addRemix(String name, ToDoubleFunction<BasisValues> remix, double weight, Runnable callback) {
add(name, EvalType.remix, remix, null, weight, callback);
}
public void addRemix(String name, ToDoubleFunction<DoubleMap> remix, double weight) {
public void addRemix(String name, ToDoubleFunction<BasisValues> remix, double weight) {
add(name, EvalType.remix, remix, null, weight, null);
}
@ -145,7 +145,7 @@ public class SimFrameCapture implements SimFrameResults {
throw new RuntimeException("cant start window twice in a row. Must close window first");
}
int nextidx = this.allFrames.size();
DoubleMap vars = new DoubleMap();
BasisValues vars = new BasisValues();
List<FrameSample> samples = criteria.stream().map(c -> FrameSample.init(c, nextidx, vars).start(now)).toList();
this.currentFrame = new FrameSampleSet(samples);
// System.out.println("after start:\n"+ frameCaptureSummary(currentFrame));
@ -177,7 +177,7 @@ public class SimFrameCapture implements SimFrameResults {
return allFrames.getLast();
}
public void addRemix(String name, ToDoubleFunction<DoubleMap> remix) {
public void addRemix(String name, ToDoubleFunction<BasisValues> remix) {
addRemix(name, remix, 1.0, null);
}

View File

@ -21,6 +21,9 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Aggregate usage patterns around capturing and using simulation frame data.
*/
public class SimFrameJournal extends ArrayList<SimFrame> implements JournalView {
public void record(SimFrameParams params, FrameSampleSet samples) {
add(new SimFrame(params, samples));

View File

@ -16,8 +16,14 @@
package io.nosqlbench.scenarios.findmax;
/**
* These parameters are calculated by the planner based on previous simulation frame history.
*/
public record SimFrameParams(
double rate_shelf, double rate_delta, long sample_time_ms, String description
double rate_shelf,
double rate_delta,
long sample_time_ms,
String description
) {
public double computed_rate() {
return rate_shelf+rate_delta;

View File

@ -31,24 +31,12 @@ public class SimFramePlanner {
* Search params which control findmax
*/
private final FindmaxSearchParams findmax;
/**
* A history of execution parameters by step
*/
/**
* A history of execution results by step
*/
public SimFramePlanner(FindmaxSearchParams findMaxSettings) {
this.findmax = findMaxSettings;
}
public boolean conditionsMet() {
return false;
}
public SimFrameParams initialStep() {
return new SimFrameParams(
this.findmax.rate_base(), this.findmax.rate_step(), this.findmax.sample_time_ms(), "INITIAL"
@ -74,7 +62,8 @@ public class SimFramePlanner {
last.params().sample_time_ms(),
"CONTINUE after improvement from frame " + last.index()
);
} else if (best.index() == last.index() - 1) { // got worse consecutively
} else if (best.index() == last.index() - 1) {
// got worse consecutively, this may be collapsed out since the general case below covers it (test first)
if ((last.params().computed_rate() - best.params().computed_rate()) <= findmax.rate_step()) {
logger.info("could not divide search space further, stop condition met");
return null;
@ -86,13 +75,13 @@ public class SimFramePlanner {
"REBASE search range to new base after frame " + best.index()
);
}
} else {
} else { // any other case
// find next frame with higher rate but lower value, the closest one by rate
SimFrame nextWorseFrameWithHigherRate = journal.frames().stream()
.filter(f -> f.value() < best.value())
.filter(f -> f.params().computed_rate() > best.params().computed_rate())
.min(Comparator.comparingDouble(f -> f.params().computed_rate()))
.orElseThrow(() -> new RuntimeException("inconsistent result"));
.orElseThrow(() -> new RuntimeException("inconsistent samples"));
if ((nextWorseFrameWithHigherRate.params().computed_rate() - best.params().computed_rate()) > findmax.rate_step()) {
return new SimFrameParams(
best.params().computed_rate(),
@ -101,13 +90,10 @@ public class SimFramePlanner {
"REBASE search range from frames " + best.index() + "" +nextWorseFrameWithHigherRate.index()
);
} else {
logger.info("could not divide search space further, stop condition met");
return null;
}
}
}
private boolean improvedScore(SimFrame before, SimFrame last) {
return before.value() < last.value();
}
}

View File

@ -18,10 +18,11 @@ package io.nosqlbench.scenarios.findmax;
import java.util.List;
/**
* An observer-only view of results.
*/
public interface SimFrameResults {
List<FrameSampleSet> history();
double getValue();
int size();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -0,0 +1,800 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
sodipodi:docname="findmax.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="true"
inkscape:zoom="2.8573542"
inkscape:cx="394.07085"
inkscape:cy="466.3405"
inkscape:window-width="3440"
inkscape:window-height="1359"
inkscape:window-x="227"
inkscape:window-y="2160"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<inkscape:grid
id="grid1"
units="in"
originx="0"
originy="0"
spacingx="1.5875"
spacingy="1.5875"
empcolor="#0099e5"
empopacity="0.30196078"
color="#0099e5"
opacity="0.14901961"
empspacing="16"
dotted="false"
gridanglex="30"
gridanglez="30"
visible="true" />
</sodipodi:namedview>
<defs
id="defs1">
<marker
style="overflow:visible"
id="ArrowWideHeavy"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Wide, heavy arrow"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="m 1,0 -3,3 h -2 l 3,-3 -3,-3 h 2 z"
id="path3" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-3" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-2-8"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-3-8" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-2-8-8"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-3-8-7" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-1-8"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-3-2" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-6-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-6-3" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-2-5-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-3-6-8" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-2-8-5-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-3-8-6-9" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-1-8-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-3-2-0" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-6-6-0"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-6-3-8" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-1-8-2-1"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-3-2-0-9" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-6-6-0-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-6-3-8-9" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-1-8-2-1-5"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-3-2-0-9-3" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-6" />
</marker>
<marker
style="overflow:visible"
id="ColoredDot-4-21"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Colored dot"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
sodipodi:nodetypes="sssss"
id="path20-8-7" />
</marker>
<marker
style="overflow:visible"
id="ArrowWideHeavy-8"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Wide, heavy arrow"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="m 1,0 -3,3 h -2 l 3,-3 -3,-3 h 2 z"
id="path3-9" />
</marker>
<marker
style="overflow:visible"
id="ArrowWideHeavy-8-0"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Wide, heavy arrow"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="m 1,0 -3,3 h -2 l 3,-3 -3,-3 h 2 z"
id="path3-9-7" />
</marker>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#ColoredDot-4)"
id="rect21"
width="119.0625"
height="76.199997"
x="44.450001"
y="77.787498" />
<path
style="font-variation-settings:normal;fill:#dedede;fill-opacity:1;stroke:none;stroke-width:0.459;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.492421;stop-color:#000000"
d="m 113.39225,126.57179 c 1.55868,-1.45047 2.60997,-7.5093 4.08275,-7.5093 1.55804,0 2.07751,3.73502 6.33258,3.37384 0,0 -3.89089,0.28382 -5.72926,0.8209 -1.83837,0.53707 -4.68607,3.31456 -4.68607,3.31456 z"
id="path5-4"
sodipodi:nodetypes="czczc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="M 100.0125,93.662496 V 149.22499"
id="path9-5-8-4"
sodipodi:nodetypes="cc" />
<path
style="fill:#000000;fill-opacity:0.549119;stroke:#000000;stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
d="M 50.8,150.81249 H 160.3375"
id="path4"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#0e00f4;stroke-width:0.458922;stroke-dasharray:none;stroke-opacity:0.492421;font-variation-settings:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
d="m 50.786531,149.24737 c 22.230465,-10.02781 30.169917,-11.142 38.109369,-12.25621 7.939452,-1.1142 11.11523,-1.1142 17.4668,-4.4568 6.35156,-3.34261 7.93945,-10.02781 15.8789,-10.02781 7.93945,0 5.41852,-4.88669 14.29101,2.22841 11.11524,8.9136 15.87891,16.713 23.81836,20.0556"
id="path5"
sodipodi:nodetypes="cssssc" />
<g
id="g8"
transform="translate(1.4059337e-6,-9.5249941)">
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
d="m 50.799999,101.59999 v 3.175"
id="path6" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot)"
d="m 50.799999,103.18749 h 1.5875"
id="path7" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4)"
d="m 52.3875,103.1875 h 3.175"
id="path7-0"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);stop-color:#000000;stop-opacity:1"
d="m 55.562499,103.18749 h 6.35"
id="path8" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-2)"
d="M 61.9125,103.1875 H 74.612501"
id="path7-0-2"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-2-8)"
d="M 74.612501,103.1875 H 100.0125"
id="path7-0-2-4"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-2-8-8)"
d="m 100.0125,103.1875 h 50.8"
id="path7-0-2-4-4"
sodipodi:nodetypes="cc" />
</g>
<g
id="g8-6-1"
transform="translate(49.2125,-3.1750043)">
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
d="m 50.799999,101.59999 v 3.175"
id="path6-4-5" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-1-8)"
d="m 50.799999,103.18749 h 1.5875"
id="path7-5-9" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-6-6)"
d="m 52.3875,103.1875 h 3.175"
id="path7-0-1-6"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4-6-6);stop-color:#000000;stop-opacity:1"
d="m 55.562499,103.18749 h 6.35"
id="path8-4-1" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-2-5-9)"
d="M 61.9125,103.1875 H 74.612501"
id="path7-0-2-3-6"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-2-8-5-6)"
d="M 74.612501,103.1875 H 100.0125"
id="path7-0-2-4-1-5"
sodipodi:nodetypes="cc" />
</g>
<g
id="g8-6-1-8"
transform="translate(73.025002,3.1750054)">
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
d="m 50.799999,101.59999 v 3.175"
id="path6-4-5-7" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-1-8-2)"
d="m 50.799999,103.18749 h 1.5875"
id="path7-5-9-8" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-6-6-0)"
d="m 52.3875,103.1875 h 3.175"
id="path7-0-1-6-3"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4-6-6-0);stop-color:#000000;stop-opacity:1"
d="m 55.562499,103.18749 h 6.35"
id="path8-4-1-2" />
</g>
<g
id="g8-6-1-8-1"
transform="translate(77.787501,9.5249951)">
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
d="m 50.799999,101.59999 v 3.175"
id="path6-4-5-7-9" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-1-8-2-1)"
d="m 50.799999,103.18749 h 0.784962 0.802538 m 1e-6,1e-5 0,0"
id="path7-5-9-8-6"
sodipodi:nodetypes="ccccc" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-4-6-6-0-9)"
d="m 52.3875,103.1875 h 3.175"
id="path7-0-1-6-3-8"
sodipodi:nodetypes="cc" />
</g>
<g
id="g8-6-1-8-1-7"
transform="translate(79.375002,14.287505)">
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
d="m 50.799999,101.59999 v 3.175"
id="path6-4-5-7-9-3" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-1-8-2-1-5)"
d="m 50.799999,103.18749 h 0.784962 0.802538 m 1e-6,1e-5 v 0"
id="path7-5-9-8-6-2"
sodipodi:nodetypes="ccccc" />
</g>
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 101.6,100.0125 0,39.68749"
id="path9-73"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 104.775,100.01249 0,39.6875"
id="path9-6"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 111.125,100.0125 0,39.68749"
id="path9-51"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 123.825,100.0125 0,39.68748"
id="path9-51-7"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 52.3875,93.662496 0,55.562494"
id="path9-5"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="M 55.5625,93.662496 V 149.22499"
id="path9-5-7"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="M 61.9125,93.662496 V 149.22499"
id="path9-5-4"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="M 74.612501,93.662496 V 149.22499"
id="path9-5-8"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 125.4125,106.3625 0,0 v 23.81249"
id="path9-4-7"
sodipodi:nodetypes="ccc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 128.5875,106.3625 0,0 v 23.81249"
id="path9-4-4"
sodipodi:nodetypes="ccc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#4bb300;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25, 0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);stop-color:#000000;stop-opacity:1"
d="m 130.175,112.7125 v 0 l 0,14.28749"
id="path9-4-4-1"
sodipodi:nodetypes="ccc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#ff2828;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25, 0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);stop-color:#000000;stop-opacity:1"
d="m 131.7625,119.06249 v -1.5875 l 0,6.35"
id="path9-4-4-1-9"
sodipodi:nodetypes="ccc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#ff2828;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25, 0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);stop-color:#000000;stop-opacity:1"
d="m 133.35,112.7125 v 0 l 0,14.28749"
id="path9-4-4-15"
sodipodi:nodetypes="ccc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#ff2828;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 134.9375,106.3625 0,0 v 23.81249"
id="path9-4-2"
sodipodi:nodetypes="ccc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#ff2828;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4);opacity:1;stop-color:#000000;stop-opacity:1"
d="m 149.225,100.0125 0,39.68749"
id="path9-7"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;opacity:1;fill:none;fill-opacity:0.549119;stroke:#ff2828;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.25,0.25;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#ColoredDot-4)"
d="m 150.8125,93.662496 0,55.562494"
id="path10"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#ff2929;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
d="m 130.175,112.7125 c 0,0 0,-1.5875 1.5875,-1.5875 1.5875,0 1.5875,1.5875 1.5875,1.5875 0,0 -1.5875,10e-6 -1.5875,1.5875 l 0,3.17499"
id="path18"
sodipodi:nodetypes="cscsc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#52c800;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
d="m 134.9375,106.3625 c 0,0 -2.05247,0.46496 -3.175,1.5875 -1.5875,1.5875 -1.5875,4.7625 -1.5875,4.7625"
id="path17" />
<path
style="font-variation-settings:normal;opacity:1;fill:none;fill-opacity:0.549119;stroke:#ff2929;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
d="m 128.5875,106.3625 c 0,0 0,-1.5875 3.175,-1.5875 3.175,0 3.175,1.5875 3.175,1.5875"
id="path16" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#52c800;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
d="m 149.225,100.0125 c 0,0 -3.3694,1.5875 -7.9375,1.5875 0,0 -12.7,0 -14.2875,1.5875 -1.5875,1.5875 -1.5875,3.175 -1.5875,3.175 0,0 0,-1.5875 1.5875,-1.5875 1.5875,0 1.5875,1.5875 1.5875,1.5875"
id="path15" />
<path
style="font-variation-settings:normal;opacity:1;fill:none;fill-opacity:0.549119;stroke:#ff2929;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;vector-effect:none;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
d="m 123.825,100.0125 c 0,0 0,-1.587504 12.7,-1.587504 12.7,0 12.7,1.587504 12.7,1.587504"
id="path14" />
<path
style="font-variation-settings:normal;opacity:1;fill:none;fill-opacity:0.549119;stroke:#52c800;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1;vector-effect:none;-inkscape-stroke:none"
d="m 150.8125,93.662494 c 0,0 -12.7,1.587502 -19.05,1.587502 H 117.475 c -17.4625,0 -15.875,4.762504 -15.875,4.762504 0,0 0,-1.587504 1.5875,-1.587504 1.5875,0 1.5875,1.587504 1.5875,1.587504 0,0 0,-1.587504 3.175,-1.587504 3.175,0 3.175,1.587504 3.175,1.587504 0,0 0,-1.587504 6.35,-1.587504 6.35,0 6.35,1.587504 6.35,1.587504"
id="path13" />
<path
style="font-variation-settings:normal;opacity:1;fill:none;fill-opacity:0.549119;stroke:#ff2929;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
d="m 100.0125,93.662494 c 0,0 -3.175,-1.587498 23.8125,-1.587498 26.9875,0 26.9875,1.587498 26.9875,1.587498"
id="path12" />
<path
style="font-variation-settings:normal;opacity:1;fill:none;fill-opacity:0.549119;stroke:#52c800;stroke-width:0.33;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
d="m 52.387499,93.662494 c 0,0 1e-6,-1.587498 1.587501,-1.587498 1.5875,0 1.587499,1.587498 1.587499,1.587498 0,0 10e-7,-1.587498 3.175001,-1.587498 3.175,0 3.174999,1.587498 3.174999,1.587498 0,0 2e-6,-1.587498 6.350002,-1.587498 6.35,0 6.349998,1.587498 6.349998,1.587498 0,0 2e-6,-1.587498 12.700002,-1.587498 12.699999,0 12.699999,1.587498 12.699999,1.587498"
id="path11" />
<g
id="g19"
transform="translate(-54.287874,0.50640742)">
<g
id="g8-9"
transform="translate(72.917394,-20.669897)">
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
d="m 50.799999,101.59999 v 3.175"
id="path6-1" />
<path
style="fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ColoredDot-6)"
d="m 50.799999,103.18749 h 6.35"
id="path7-03"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:0.549119;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4-21);stop-color:#000000;stop-opacity:1"
d="m 57.149999,103.18749 h 14.2875"
id="path8-42"
sodipodi:nodetypes="cc" />
</g>
<text
xml:space="preserve"
style="font-size:2.11003px;font-variation-settings:normal;text-align:center;text-anchor:middle;white-space:pre;inline-size:9.69963;display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.166144;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4)"
x="54.405743"
y="162.52376"
id="text18"
transform="translate(66.136143,-75.243665)"><tspan
x="54.405743"
y="162.52376"
id="tspan2">base</tspan></text>
<text
xml:space="preserve"
style="font-size:2.11003px;font-variation-settings:normal;text-align:center;text-anchor:middle;white-space:pre;inline-size:9.69963;display:inline;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.166144;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4)"
x="54.405743"
y="162.52376"
id="text18-2"
transform="translate(60.206624,-78.892669)"><tspan
x="54.405743"
y="162.52376"
id="tspan3">Legend</tspan></text>
<text
xml:space="preserve"
style="font-size:2.11003px;font-variation-settings:normal;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.166144;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4)"
x="125.30489"
y="87.28009"
id="text18-1"><tspan
sodipodi:role="line"
id="tspan18-9"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.166144;stroke-dasharray:none;stroke-opacity:1"
x="125.30489"
y="87.28009">step</tspan></text>
<text
xml:space="preserve"
style="font-size:2.11003px;font-variation-settings:normal;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.166144;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ColoredDot-4)"
x="133.24239"
y="87.28009"
id="text18-1-3"><tspan
sodipodi:role="line"
id="tspan18-9-9"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.166144;stroke-dasharray:none;stroke-opacity:1"
x="133.24239"
y="87.28009">step x incr</tspan></text>
<path
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ArrowWideHeavy)"
d="m 115.77989,85.69259 h 7.9375"
id="path19"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ArrowWideHeavy-8)"
d="m 123.71739,85.69259 h 6.35"
id="path19-5"
sodipodi:nodetypes="cc" />
<path
style="font-variation-settings:normal;vector-effect:none;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker-end:url(#ArrowWideHeavy-8-0)"
d="m 130.31739,85.69259 h 14.0375"
id="path19-5-8"
sodipodi:nodetypes="cc" />
<rect
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="rect19"
width="39.687496"
height="9.525013"
x="107.95"
y="79.375"
ry="3.174998" />
</g>
<text
xml:space="preserve"
style="font-size:3.175px;font-variation-settings:normal;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.458999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.492421;marker-end:url(#ColoredDot-4)"
x="50.799999"
y="98.424995"
id="text19"><tspan
sodipodi:role="line"
id="tspan19"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.459"
x="50.799999"
y="98.424995">0</tspan></text>
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#bababa;stroke-width:0.148058;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect20"
width="5.0309258"
height="2.0002527"
x="127.62572"
y="120.16322"
ry="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -62,7 +62,7 @@ bindings:
# same as long -> NumberNameToString() -> String; String -> ToByteBuffer()
string_bb: NumberNameToString(); ToByteBuffer(); ToHexString();
# char buffer to byte buffer, another way to get the same result as above
# char buffer to byte buffer, another way to get the same samples as above
# same as
# long -> NumberNameToString() -> String; String -> ToCharBuffer() -> CharBuffer; CharBuffer -> ToByteBuffer() -> ByteBuffer
cb_bb: NumberNameToString(); ToCharBuffer(); ToByteBuffer(); ToHexString();

View File

@ -27,7 +27,7 @@ bindings:
# with a source function which provides the initial data. Any
# object type is allowed, as the toString() method is used to iteratively
# fill the initial buffer until it is full according to the imgsize
# This mode still only provides a single possible result.
# This mode still only provides a single possible samples.
#
# Create a CharBuffer of 100 characters from the names of numbers
cb_composed_fixed: CharBufImage(NumberNameToString(),100) # srcfunc, imgsize
@ -35,7 +35,7 @@ bindings:
# Alternately, you can simply provide a set of printable characters and
# ranges from US-ASCII instead of providing a full function. In this mode,
# characters are selected from the provided set for the initial fill.
# This mode still only provides a single possible result.
# This mode still only provides a single possible samples.
#
# Create a CharBuffer of 100 characters consisting of hexadecimal digits.
cb_charsets_fixed: CharBufImage('0-9A-F',100) # srcchars, imgsize

View File

@ -22,7 +22,7 @@ bindings:
# the entry above
# You can offset the start of your millis to some formatted date.
# Notice, that in this case, the result is still in millis since the epoch
# Notice, that in this case, the samples is still in millis since the epoch
randomMillisStartingFeb2018: StartingEpochMillis('2018-02-01 05:00:00');

View File

@ -90,13 +90,13 @@ class ExitStatusIntegrationTests {
// public void testCloseErrorHandlerOnSpace() {
// ProcessInvoker invoker = new ProcessInvoker();
// invoker.setLogDir("logs/test");
// ProcessResult result = invoker.run("exitstatus_erroronclose", 30,
// ProcessResult samples = invoker.run("exitstatus_erroronclose", 30,
// java, "-jar", JARNAME, "--logs-dir", "logs/test/error_on_close", "run",
// "driver=diag", "threads=2", "rate=5", "op=noop", "cycles=10", "erroronclose=true", "-vvv"
// );
// String stdout = String.join("\n", result.getStdoutData());
// String stderr = String.join("\n", result.getStderrData());
// assertThat(result.exitStatus).isEqualTo(2);
// String stdout = String.join("\n", samples.getStdoutData());
// String stderr = String.join("\n", samples.getStderrData());
// assertThat(samples.exitStatus).isEqualTo(2);
// assertThat(stderr).contains("diag space was configured to throw");
// }

View File

@ -35,7 +35,7 @@ public class ProcessInvoker {
/**
* Run the process with a specified timeout and alias.
*
* @param alias the name of the process for logging and result gathering
* @param alias the name of the process for logging and samples gathering
* @param timeoutSeconds the number of seconds to wait for the process to return
* @param cmdline the command line
* @return a ProcessResult

View File

@ -39,7 +39,7 @@ public class ProcessResult {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("--- process result\nstatus:%d", exitStatus));
sb.append(String.format("--- process samples\nstatus:%d", exitStatus));
sb.append(String.format(" time:%.3fs", (durationNanos/1000000000.0)));
sb.append(String.format(" dir:%s",cmdDir));
sb.append("\n--- stdout:\n");