mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
findmax 80% ready
This commit is contained in:
parent
bff86b5525
commit
137ce31136
@ -17,6 +17,7 @@
|
||||
package io.nosqlbench.engine.core.lifecycle.scenario.context;
|
||||
|
||||
import io.nosqlbench.api.config.standard.TestComponent;
|
||||
import io.nosqlbench.api.filtering.TristateFilter;
|
||||
import io.nosqlbench.components.NBComponent;
|
||||
import io.nosqlbench.engine.api.scripting.DiagReader;
|
||||
import io.nosqlbench.engine.api.scripting.DiagWriter;
|
||||
@ -25,10 +26,23 @@ import io.nosqlbench.engine.api.scripting.InterjectingCharArrayWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Map;
|
||||
|
||||
public class NBSceneBuffer implements NBSceneFixtures {
|
||||
private final NBSceneFixtures fixtures;
|
||||
|
||||
public NBSceneBuffer params(Map<String,String> params) {
|
||||
return new NBSceneBuffer(
|
||||
new NBDefaultSceneFixtures(
|
||||
ScenarioParams.of(params),
|
||||
fixtures.controller(),
|
||||
fixtures.out(),
|
||||
fixtures.err(),
|
||||
fixtures.in())
|
||||
,iotype
|
||||
);
|
||||
}
|
||||
|
||||
public enum IOType {
|
||||
connected,
|
||||
virtual,
|
||||
|
@ -102,8 +102,8 @@ public class ScenarioActivitiesController extends NBBaseComponent {
|
||||
*
|
||||
* @param alias the alias of an activity that is already known to the scenario
|
||||
*/
|
||||
public synchronized void start(String alias) {
|
||||
start(ActivityDef.parseActivityDef(alias));
|
||||
public Activity start(String alias) {
|
||||
return start(ActivityDef.parseActivityDef(alias));
|
||||
}
|
||||
|
||||
public synchronized void run(int timeout, Map<String, String> activityDefMap) {
|
||||
|
@ -24,10 +24,7 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.graalvm.polyglot.Value;
|
||||
import org.graalvm.polyglot.proxy.ProxyObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -180,6 +177,10 @@ public class ScenarioParams extends HashMap<String, String> implements ProxyObje
|
||||
public void putMember(String key, Value value) {
|
||||
super.put(key, value.asString());
|
||||
}
|
||||
|
||||
public Optional<String> maybeGet(String name) {
|
||||
return Optional.ofNullable(get(name));
|
||||
}
|
||||
//endregion
|
||||
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ public class ScenariosExecutor extends NBBaseComponent {
|
||||
} catch (Exception e) {
|
||||
long now = System.currentTimeMillis();
|
||||
logger.debug("creating exceptional scenario result from getAsyncResultStatus");
|
||||
throw new RuntimeException("replace with a proper error type: " + e.toString(),e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package io.nosqlbench.engine.core.lifecycle.session;
|
||||
|
||||
import io.nosqlbench.api.engine.metrics.instruments.NBFunctionGauge;
|
||||
import io.nosqlbench.api.labels.NBLabeledElement;
|
||||
import io.nosqlbench.api.spi.SimpleServiceLoader;
|
||||
import io.nosqlbench.components.NBComponent;
|
||||
@ -168,6 +169,8 @@ public class NBSession extends NBBaseComponent implements Function<List<Cmd>, Ex
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction;
|
||||
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -57,6 +58,7 @@ public class TestOptimoExperiments2 {
|
||||
|
||||
private final static Logger logger = LogManager.getLogger(TestOptimoExperiments2.class);
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testBrokenParams() {
|
||||
|
||||
|
@ -19,6 +19,5 @@ package io.nosqlbench.components;
|
||||
public interface NBComponentServices {
|
||||
|
||||
public NBCreators create();
|
||||
|
||||
public NBFinders find();
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.components;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NBComponentViews {
|
||||
public static String treeView(NBComponent node) {
|
||||
return treeView(new StringBuilder(), node, 0, Object::toString);
|
||||
}
|
||||
|
||||
public static String treeView(NBComponent node, Function<NBComponent,String> representer) {
|
||||
return treeView(new StringBuilder(), node, 0, representer);
|
||||
}
|
||||
private static String treeView(StringBuilder sb, NBComponent node, int level, Function<NBComponent,String> stringify) {
|
||||
sb.append(" ".repeat(level)).append(stringify.apply(node)).append("\n");
|
||||
for (NBComponent child : node.getChildren()) {
|
||||
treeView(sb,child,level+1,stringify);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -18,4 +18,8 @@ package io.nosqlbench.components.events;
|
||||
|
||||
import io.nosqlbench.components.UpEvent;
|
||||
|
||||
public record ParamChange<T>(T value) implements UpEvent {}
|
||||
public record ParamChange<T>(T value) implements UpEvent {
|
||||
public static <T> ParamChange<T> of(T value) {
|
||||
return new ParamChange<>(value);
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.components;
|
||||
|
||||
import io.nosqlbench.api.config.standard.TestComponent;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class NBComponentViewsTest {
|
||||
@Test
|
||||
public void testBasicTreeView() {
|
||||
var root1 = new TestComponent("a", "b");
|
||||
var cd = new TestComponent(root1, "c", "d");
|
||||
var UV = new TestComponent(cd, "U", "V");
|
||||
var YZ = new TestComponent(cd, "Y", "Z");
|
||||
var ef = new TestComponent(root1, "e", "f");
|
||||
|
||||
var root2 = new TestComponent("a", "b");
|
||||
|
||||
root2.attachChild(new TestComponent(root2, "c", "d")
|
||||
.attachChild(new TestComponent("U", "V"))
|
||||
.attachChild(new TestComponent("Y", "Z")))
|
||||
.attachChild(new TestComponent("e", "f"));
|
||||
|
||||
System.out.println("root1:\n" + NBComponentViews.treeView(root1));
|
||||
System.out.println("root1:\n" + NBComponentViews.treeView(root1, c -> String.valueOf(c.hashCode())));
|
||||
|
||||
System.out.println("root2:\n" + NBComponentViews.treeView(root2));
|
||||
System.out.println("root2:\n" + NBComponentViews.treeView(root2, c -> String.valueOf(c.hashCode())));
|
||||
}
|
||||
|
||||
}
|
@ -98,12 +98,15 @@ public class DirectRuntimeScenarioTests {
|
||||
ScenarioResult result = scenario.apply(NBSceneBuffer.traced(scenario));
|
||||
result.report();
|
||||
}
|
||||
|
||||
|
||||
@Disabled("enable before merge")
|
||||
@Test
|
||||
public void test_SC_cocycledelay_strict() {
|
||||
NBScenario scenario = new SC_cocycledelay_strict(testC,"test_SC_cocycledelay_strict");
|
||||
ScenarioResult result = scenario.apply(NBSceneBuffer.traced(scenario));
|
||||
}
|
||||
|
||||
@Disabled("enable before merge")
|
||||
@Test
|
||||
public void test_SC_cycle_rate() {
|
||||
@ -184,7 +187,6 @@ public class DirectRuntimeScenarioTests {
|
||||
NBScenario scenario = new SC_start_stop_diag(testC,"test_SC_start_stop_diag");
|
||||
ScenarioResult result = scenario.apply(NBSceneBuffer.traced(scenario));
|
||||
}
|
||||
@Disabled("enable before merge")
|
||||
@Test
|
||||
public void test_SC_threadchange() {
|
||||
NBScenario scenario = new SC_threadchange(testC,"test_SC_threadchange");
|
||||
@ -196,12 +198,12 @@ public class DirectRuntimeScenarioTests {
|
||||
NBScenario scenario = new SC_threadspeeds(testC,"test_SC_threadspeeds");
|
||||
ScenarioResult result = scenario.apply(NBSceneBuffer.traced(scenario));
|
||||
}
|
||||
@Disabled("enable before merge")
|
||||
|
||||
@Test
|
||||
public void test_SC_undef_param() {
|
||||
NBScenario scenario = new SC_undef_param(testC, "test_SC_undef_param");
|
||||
ScenarioResult result = scenario.apply(NBSceneBuffer.traced(scenario));
|
||||
ScenarioResult result = scenario.apply(NBSceneBuffer.traced(scenario).params(Map.of("one", "two", "three", "four")));
|
||||
String out = result.getIOLog();
|
||||
assertThat(out).contains("foobar");
|
||||
assertThat(out).matches(Pattern.compile(".*after overriding .*:null.*",Pattern.DOTALL));
|
||||
}
|
||||
}
|
||||
|
@ -39,5 +39,16 @@ public class SC_threadchange extends SCBaseScenario {
|
||||
@Override
|
||||
public void invoke() {
|
||||
|
||||
var activity = controller.start("driver=diag;alias=threadchange;cycles=0..60000;threads=1;interval=2000;op='noop';rate=1000");
|
||||
activity.getActivityDef().setThreads(1);
|
||||
stdout.println("threads now " + activity.getActivityDef().getThreads());
|
||||
stdout.println("waiting 500 ms");
|
||||
controller.waitMillis(500);
|
||||
|
||||
activity.getActivityDef().setThreads(5);
|
||||
stdout.println("threads now " + activity.getActivityDef().getThreads());
|
||||
controller.stop("threadchange");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios;
|
||||
|
||||
import java.util.function.DoubleSupplier;
|
||||
|
||||
public abstract class BasePerfDimension implements PerfDimension {
|
||||
private double weight;
|
||||
private DoubleSupplier supplier;
|
||||
private String name;
|
||||
private Weighting weighting = Weighting.uniform;
|
||||
|
||||
public BasePerfDimension(String name, double weight, Weighting weighting, DoubleSupplier supplier) {
|
||||
this.weight = weight;
|
||||
this.supplier = supplier;
|
||||
this.name = name;
|
||||
this.weighting = weighting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWeight() {
|
||||
return this.weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoubleSupplier getSupplier() {
|
||||
return supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weighting getWeighting() {
|
||||
return weighting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract String getValue();
|
||||
}
|
@ -29,6 +29,7 @@ import io.nosqlbench.engine.api.activityapi.core.Activity;
|
||||
import io.nosqlbench.engine.api.activityapi.ratelimits.simrate.CycleRateSpec;
|
||||
import io.nosqlbench.engine.api.activityapi.ratelimits.simrate.SimRateSpec;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.direct.SCBaseScenario;
|
||||
import io.nosqlbench.scenarios.findmax.SimFrameCapture;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@ -87,7 +88,7 @@ public class SC_optimo extends SCBaseScenario {
|
||||
|
||||
flywheel.onEvent(new ParamChange<>(new CycleRateSpec(5.0, 1.1d, SimRateSpec.Verb.restart)));
|
||||
|
||||
PerfWindowSampler sampler = new PerfWindowSampler();
|
||||
SimFrameCapture sampler = new SimFrameCapture();
|
||||
NBMetricTimer result_success_timer = flywheel.find().timer("name:result_success");
|
||||
System.out.println("c1:" + result_success_timer.getCount());
|
||||
sampler.addDeltaTime("achieved_rate", result_success_timer::getCount, 1000.0);
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.context.ScenarioParams;
|
||||
|
||||
public record FindmaxSearchParams(
|
||||
int sample_time_ms,
|
||||
int sample_max,
|
||||
double sample_incr,
|
||||
double rate_base,
|
||||
double rate_step,
|
||||
double rate_incr,
|
||||
double average_of,
|
||||
double latency_cutoff,
|
||||
double latency_pctile,
|
||||
double testrate_cutoff,
|
||||
double bestrate_cutoff
|
||||
) {
|
||||
public FindmaxSearchParams(ScenarioParams params) {
|
||||
this(
|
||||
params.maybeGet("sample_time_ms").map(Integer::parseInt).orElse(1000),
|
||||
params.maybeGet("sample_max").map(Integer::parseInt).orElse(10000),
|
||||
params.maybeGet("sample_incr").map(Double::parseDouble).orElse(1.01d),
|
||||
params.maybeGet("rate_base").map(Double::parseDouble).orElse(0d),
|
||||
params.maybeGet("rate_step").map(Double::parseDouble).orElse(100d),
|
||||
params.maybeGet("rate_incr").map(Double::parseDouble).orElse(2.0d),
|
||||
params.maybeGet("average_of").map(Integer::parseInt).orElse(2),
|
||||
params.maybeGet("latency_cutoff").map(Double::parseDouble).orElse(50.0d),
|
||||
params.maybeGet("testrate_cutoff").map(Double::parseDouble).orElse(0.8),
|
||||
params.maybeGet("bestrate_cutoff").map(Double::parseDouble).orElse(0.90),
|
||||
params.maybeGet("latency_pctile").map(Double::parseDouble).orElse(0.99)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface JournalView {
|
||||
List<SimFrame> frames();
|
||||
SimFrame last();
|
||||
SimFrame beforeLast();
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import io.nosqlbench.api.engine.metrics.instruments.NBFunctionGauge;
|
||||
import io.nosqlbench.api.engine.metrics.instruments.NBMetricGauge;
|
||||
import io.nosqlbench.api.engine.metrics.instruments.NBMetricTimer;
|
||||
import io.nosqlbench.components.NBComponent;
|
||||
import io.nosqlbench.components.events.ParamChange;
|
||||
import io.nosqlbench.engine.api.activityapi.core.Activity;
|
||||
import io.nosqlbench.engine.api.activityapi.ratelimits.simrate.CycleRateSpec;
|
||||
import io.nosqlbench.engine.api.activityapi.ratelimits.simrate.SimRateSpec;
|
||||
import io.nosqlbench.engine.core.lifecycle.scenario.direct.SCBaseScenario;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
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>
|
||||
*/
|
||||
public class SC_findmax extends SCBaseScenario {
|
||||
private final static Logger logger = LogManager.getLogger(SC_findmax.class);
|
||||
|
||||
public SC_findmax(NBComponent parentComponent, String scenarioName) {
|
||||
super(parentComponent, scenarioName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke() {
|
||||
// TODO: having "scenario" here as well as in "named scenario" in workload templates is confusing. Make this clearer.
|
||||
String workload = params.getOrDefault("workload", "default_workload");
|
||||
|
||||
Map<String, String> activityParams = new HashMap<>(Map.of(
|
||||
"cycles", String.valueOf(Long.MAX_VALUE),
|
||||
"threads", "1",
|
||||
"driver", "diag",
|
||||
"rate", "1",
|
||||
"dryrun", "op"
|
||||
));
|
||||
if (params.containsKey("workload")) {
|
||||
activityParams.put("workload", params.get("workload"));
|
||||
} else if (params.containsKey("op")) {
|
||||
activityParams.put("op", params.get("op"));
|
||||
} else {
|
||||
activityParams.put("op", "log: level=info");
|
||||
logger.warn("You provided neither a workload nor an op, so assuming diagnostic mode.");
|
||||
}
|
||||
|
||||
FindmaxSearchParams findmaxSettings = new FindmaxSearchParams(params);
|
||||
|
||||
int seconds = findmaxSettings.sample_time_ms();
|
||||
// double target_rate = findmaxSettings.rate_base() + findmaxSettings.rate_step();
|
||||
|
||||
Activity flywheel = controller.start(activityParams);
|
||||
final double[] target_rate = new double[] {findmaxSettings.rate_step()};
|
||||
NBFunctionGauge targetRateGauge = flywheel.create().gauge("target_rate", () -> target_rate[0]);
|
||||
// stdout.println("warming up for " + seconds + " seconds");
|
||||
// controller.waitMillis(seconds * 1000);
|
||||
|
||||
SimFrameCapture capture = this.perfValueMeasures(flywheel, 0.99, 50);
|
||||
SimFramePlanner planner = new SimFramePlanner(findmaxSettings);
|
||||
SimFrameJournal journal = new SimFrameJournal();
|
||||
|
||||
SimFrameParams frameParams = planner.initialStep();
|
||||
while (frameParams!=null) {
|
||||
stdout.println("params:" + frameParams);
|
||||
target_rate[0] = frameParams.computed_rate();
|
||||
flywheel.onEvent(ParamChange.of(new CycleRateSpec(target_rate[0], 1.05d, SimRateSpec.Verb.restart)));
|
||||
capture.startWindow();
|
||||
controller.waitMillis(frameParams.sample_time_ms());
|
||||
capture.stopWindow();
|
||||
journal.record(frameParams,capture.last());
|
||||
stdout.println(capture.last());
|
||||
// stdout.println("SUMMARY:" + journal.last());
|
||||
stdout.println("-".repeat(40));
|
||||
frameParams = planner.nextStep(journal);
|
||||
}
|
||||
controller.stop(flywheel);
|
||||
|
||||
// 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) {
|
||||
SimFrameCapture sampler = new SimFrameCapture();
|
||||
|
||||
NBMetricTimer result_success_timer = activity.find().timer("name:result_success");
|
||||
NBMetricTimer result_timer = activity.find().timer("name:result");
|
||||
|
||||
// achieved rate
|
||||
sampler.addDeltaTime(
|
||||
"achieved_rate",
|
||||
result_success_timer::getCount,
|
||||
1.0
|
||||
);
|
||||
|
||||
// NBMetricGauge target_rate_gauge = activity.find().gauge("name=target_rate");
|
||||
// sampler.addDirect(
|
||||
// "achieved_ratio",
|
||||
// () -> Math.max(1.0d,(result_success_timer.getCount() / target_rate_gauge.getValue()))*Math.max(1.0d,(result_success_timer.getCount() / target_rate_gauge.getValue())),
|
||||
// 1.0
|
||||
// );
|
||||
|
||||
// // response time
|
||||
// sampler.addDirect(
|
||||
// "latency",
|
||||
// () -> {
|
||||
// double quantile_response_ns = result_success_timer.getDeltaSnapshot(1000).getValue(fractional_quantile);
|
||||
// if (quantile_response_ns * 1000000 > cutoff_ms) {
|
||||
// return 0.0d;
|
||||
// } else {
|
||||
// return quantile_response_ns;
|
||||
// }
|
||||
// },
|
||||
// -1
|
||||
// );
|
||||
//
|
||||
// // error count
|
||||
// sampler.addDeltaTime(
|
||||
// "error_rate",
|
||||
// () -> result_timer.getCount() - result_success_timer.getCount(),
|
||||
// -1
|
||||
// );
|
||||
//
|
||||
|
||||
return sampler;
|
||||
}
|
||||
|
||||
private final static record RunParams(
|
||||
int sample_seconds,
|
||||
double target_rate
|
||||
) {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
/**
|
||||
* Capture the control inputs as well as the result 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
|
||||
*/
|
||||
public record SimFrame(SimFrameParams params, SimFrameCapture.FrameSampleSet result) {
|
||||
public double value() {
|
||||
return result().value();
|
||||
}
|
||||
public int index() {
|
||||
return result.index();
|
||||
}
|
||||
|
||||
}
|
@ -14,11 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios;
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
/**
|
||||
* This is a helper class that makes it easy to bundle up a combination of measurable
|
||||
@ -29,42 +31,55 @@ import java.util.function.DoubleSupplier;
|
||||
*
|
||||
* <P>This is NOT thread safe!</P>
|
||||
*/
|
||||
public class PerfWindowSampler {
|
||||
|
||||
public class SimFrameCapture implements SimFrameResults {
|
||||
private final List<Criterion> criteria = new ArrayList<>();
|
||||
private final WindowSamples windows = new WindowSamples();
|
||||
private WindowSample window;
|
||||
private final FrameSamples allFrames = new FrameSamples();
|
||||
private FrameSampleSet currentFrame;
|
||||
|
||||
|
||||
void addDirect(String name, DoubleSupplier supplier, double weight, Runnable callback) {
|
||||
public void addDirect(String name, DoubleSupplier supplier, double weight, Runnable callback) {
|
||||
this.criteria.add(new Criterion(name, supplier, weight, callback, false));
|
||||
}
|
||||
|
||||
void addDirect(String name, DoubleSupplier supplier, double weight) {
|
||||
public void addDirect(String name, DoubleSupplier supplier, double weight) {
|
||||
addDirect(name, supplier, weight, () -> {
|
||||
});
|
||||
}
|
||||
|
||||
void addDeltaTime(String name, DoubleSupplier supplier, double weight, Runnable callback) {
|
||||
public void addDeltaTime(String name, DoubleSupplier supplier, double weight, Runnable callback) {
|
||||
this.criteria.add(new Criterion(name, supplier, weight, callback, true));
|
||||
}
|
||||
|
||||
void addDeltaTime(String name, DoubleSupplier supplier, double weight) {
|
||||
public void addDeltaTime(String name, DoubleSupplier supplier, double weight) {
|
||||
addDeltaTime(name, supplier, weight, () -> {
|
||||
});
|
||||
}
|
||||
|
||||
double getValue() {
|
||||
if (windows.size() == 0) {
|
||||
public void addDeltaTime(String name, LongSupplier supplier, double weight) {
|
||||
addDeltaTime(name, () -> (double)supplier.getAsLong(), weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FrameSampleSet> history() {
|
||||
return Collections.unmodifiableList(this.allFrames);
|
||||
}
|
||||
@Override
|
||||
public double getValue() {
|
||||
if (allFrames.isEmpty()) {
|
||||
return Double.NaN;
|
||||
}
|
||||
return windows.getLast().value();
|
||||
return allFrames.getLast().value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.allFrames.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("PERF VALUE=").append(getValue()).append("\n");
|
||||
sb.append("windows:\n" + windows.getLast().toString());
|
||||
sb.append("windows:\n" + allFrames.getLast().toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@ -73,11 +88,12 @@ public class PerfWindowSampler {
|
||||
}
|
||||
|
||||
public void startWindow(long now) {
|
||||
if (window != null) {
|
||||
if (currentFrame != null) {
|
||||
throw new RuntimeException("cant start window twice in a row. Must close window first");
|
||||
}
|
||||
List<ParamSample> samples = criteria.stream().map(c -> ParamSample.init(c).start(now)).toList();
|
||||
this.window = new WindowSample(samples);
|
||||
int nextidx = this.allFrames.size();
|
||||
List<FrameSample> samples = criteria.stream().map(c -> FrameSample.init(c,nextidx).start(now)).toList();
|
||||
this.currentFrame = new FrameSampleSet(samples);
|
||||
}
|
||||
|
||||
public void stopWindow() {
|
||||
@ -85,11 +101,11 @@ public class PerfWindowSampler {
|
||||
}
|
||||
|
||||
public void stopWindow(long now) {
|
||||
for (int i = 0; i < window.size(); i++) {
|
||||
window.set(i, window.get(i).stop(now));
|
||||
for (int i = 0; i < currentFrame.size(); i++) {
|
||||
currentFrame.set(i, currentFrame.get(i).stop(now));
|
||||
}
|
||||
windows.add(window);
|
||||
window = null;
|
||||
allFrames.add(currentFrame);
|
||||
currentFrame = null;
|
||||
}
|
||||
|
||||
public static record Criterion(
|
||||
@ -101,25 +117,42 @@ public class PerfWindowSampler {
|
||||
) {
|
||||
}
|
||||
|
||||
public static class WindowSamples extends ArrayList<WindowSample> {
|
||||
public FrameSampleSet last() {
|
||||
return allFrames.getLast();
|
||||
}
|
||||
|
||||
public static class WindowSample extends ArrayList<ParamSample> {
|
||||
public WindowSample(List<ParamSample> samples) {
|
||||
public static class FrameSamples extends ArrayList<FrameSampleSet> {
|
||||
}
|
||||
|
||||
public static class FrameSampleSet extends ArrayList<FrameSample> {
|
||||
public FrameSampleSet(List<FrameSample> samples) {
|
||||
super(samples);
|
||||
}
|
||||
|
||||
public int index() {
|
||||
return getLast().index();
|
||||
}
|
||||
public double value() {
|
||||
double product = 1.0;
|
||||
for (ParamSample sample : this) {
|
||||
for (FrameSample sample : this) {
|
||||
product *= sample.weightedValue();
|
||||
}
|
||||
|
||||
return product;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb= new StringBuilder();
|
||||
sb.append(String.format("FRAME %05d VALUE %010.5f\n", index(), value())).append("\n");
|
||||
for (FrameSample frameSample : this) {
|
||||
sb.append(" > ").append(frameSample.toString()).append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static record ParamSample(Criterion criterion, long startAt, long endAt, double startval, double endval) {
|
||||
public static record FrameSample(Criterion criterion, int index, long startAt, long endAt, double startval, double endval) {
|
||||
public double weightedValue() {
|
||||
return rawValue() * criterion().weight;
|
||||
}
|
||||
@ -139,26 +172,32 @@ public class PerfWindowSampler {
|
||||
return ((double) (endAt - startAt)) / 1000d;
|
||||
}
|
||||
|
||||
public static ParamSample init(Criterion criterion) {
|
||||
return new ParamSample(criterion, 0, 0, Double.NaN, Double.NaN);
|
||||
public static FrameSample init(Criterion criterion, int index) {
|
||||
return new FrameSample(criterion, index, 0, 0, Double.NaN, Double.NaN);
|
||||
}
|
||||
|
||||
public ParamSample start(long startTime) {
|
||||
public FrameSample start(long startTime) {
|
||||
criterion.callback.run();
|
||||
double v1 = criterion.supplier.getAsDouble();
|
||||
return new ParamSample(criterion, startTime, 0L, v1, Double.NaN);
|
||||
return new FrameSample(criterion, index, startTime, 0L, v1, Double.NaN);
|
||||
}
|
||||
|
||||
public ParamSample stop(long stopTime) {
|
||||
public FrameSample stop(long stopTime) {
|
||||
double v2 = criterion.supplier.getAsDouble();
|
||||
return new ParamSample(criterion, startAt, stopTime, startval, v2);
|
||||
return new FrameSample(criterion, index, startAt, stopTime, startval, v2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "sample[" + criterion.name() + "] "
|
||||
+ ((Double.isNaN(endval)) ? " incomplete" : "dT:" + seconds() + " dV:" + rawValue() + " rate:" + rate() + " v1:" + startval + " v2:" + endval);
|
||||
return String.format(
|
||||
"%20s %03d dt[%04.2f] dV[%010.5f] wV=%010.5f",
|
||||
criterion.name,
|
||||
index,
|
||||
seconds(),
|
||||
rawValue(),
|
||||
weightedValue()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SimFrameJournal extends ArrayList<SimFrame> implements JournalView {
|
||||
public void record(SimFrameParams params, SimFrameCapture.FrameSampleSet samples) {
|
||||
add(new SimFrame(params, samples));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SimFrame> frames() {
|
||||
return Collections.unmodifiableList(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimFrame last() {
|
||||
return super.getLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimFrame beforeLast() {
|
||||
if (size()<2) {
|
||||
throw new RuntimeException("can't get beforeLast for only " + size() + " elements");
|
||||
}
|
||||
return get(size()-2);
|
||||
}
|
||||
}
|
@ -14,18 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios;
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import java.util.function.DoubleSupplier;
|
||||
|
||||
public class Uniform extends BasePerfDimension {
|
||||
|
||||
public Uniform(double weight, DoubleSupplier supplier, String name) {
|
||||
super(name, weight, Weighting.uniform, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return null;
|
||||
public record SimFrameParams(
|
||||
double rate_shelf,
|
||||
double rate_delta,
|
||||
long sample_time_ms
|
||||
) {
|
||||
public double computed_rate() {
|
||||
return rate_shelf+rate_delta;
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2023 nosqlbench
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SimFramePlanner {
|
||||
private final Logger logger = LogManager.getLogger(SimFramePlanner.class);
|
||||
|
||||
|
||||
/**
|
||||
* 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()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using a stateful history of all control parameters and all results, decide if there
|
||||
* is additional search space and return a set of parameters for the next workload
|
||||
* simulation frame. If the stopping condition has been met, return null
|
||||
*
|
||||
* @param journal
|
||||
* All parameters and results, organized in enumerated simulation frames
|
||||
* @return Optionally, a set of params which indicates another simulation frame should be sampled, else null
|
||||
*/
|
||||
public SimFrameParams nextStep(JournalView journal) {
|
||||
List<SimFrame> frames = journal.frames();
|
||||
if (frames.size() < 2) {
|
||||
System.out.println("FIRSTTWO");
|
||||
return new SimFrameParams(
|
||||
journal.last().params().rate_shelf(),
|
||||
journal.last().params().rate_shelf() + (journal.last().params().rate_delta() * findmax.rate_incr()),
|
||||
journal.last().params().sample_time_ms()
|
||||
);
|
||||
}
|
||||
// if last result was better than the one before it
|
||||
// increment from settings
|
||||
// else if the new base would be higher than the initial rate_step
|
||||
// rebase
|
||||
// else return null;
|
||||
SimFrame last = journal.last();
|
||||
SimFrame before = journal.beforeLast();
|
||||
if (before.value() < last.value()) { // got a better result, keep on keepin' on
|
||||
System.out.println("CONTINUE");
|
||||
return new SimFrameParams(
|
||||
last.params().rate_shelf(),
|
||||
last.params().rate_delta() * findmax.rate_incr(),
|
||||
last.params().sample_time_ms()
|
||||
);
|
||||
} else { // reset to last better result as base and start again
|
||||
if (last.params().rate_delta() > findmax.rate_step()) { // but only if there is still searchable space
|
||||
System.out.println("REBASE");
|
||||
return new SimFrameParams(
|
||||
before.params().computed_rate(),
|
||||
findmax.rate_step(),
|
||||
(long) (before.params().sample_time_ms() * findmax.sample_incr()));
|
||||
} else {
|
||||
// but only if there is still unsearched resolution within rate_step
|
||||
logger.info("could not divide search space further, stop condition met");
|
||||
System.out.println("STOP CONDITION");
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SimFrameParams nextStepParams(SimFrame previous) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -14,17 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.scenarios;
|
||||
package io.nosqlbench.scenarios.findmax;
|
||||
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.List;
|
||||
|
||||
public interface PerfDimension {
|
||||
public interface SimFrameResults {
|
||||
List<SimFrameCapture.FrameSampleSet> history();
|
||||
|
||||
public double getWeight();
|
||||
|
||||
public Weighting getWeighting();
|
||||
public DoubleSupplier getSupplier();
|
||||
public String getName();
|
||||
public String getValue();
|
||||
double getValue();
|
||||
|
||||
int size();
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
|
||||
package io.nosqlbench.scenarios;
|
||||
|
||||
import io.nosqlbench.scenarios.findmax.SimFrameCapture;
|
||||
import org.assertj.core.data.Offset;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -24,11 +25,11 @@ import java.util.function.DoubleSupplier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PerfWindowSamplerTest {
|
||||
class PerfFrameSamplerTest {
|
||||
|
||||
@Test
|
||||
public void testBasicValues() {
|
||||
PerfWindowSampler pws = new PerfWindowSampler();
|
||||
SimFrameCapture pws = new SimFrameCapture();
|
||||
pws.addDirect("a",() -> 1.0d, 1.0d);
|
||||
pws.addDirect("b",()-> 3.0d, 3.0d);
|
||||
|
||||
@ -46,7 +47,7 @@ class PerfWindowSamplerTest {
|
||||
AtomicLong a2 = new AtomicLong(0);
|
||||
DoubleSupplier ds2 = () -> (double) a2.get();
|
||||
|
||||
PerfWindowSampler pws = new PerfWindowSampler();
|
||||
SimFrameCapture pws = new SimFrameCapture();
|
||||
pws.addDeltaTime("a",ds1, 1.0d);
|
||||
pws.addDeltaTime("b",ds2, 1.0d);
|
||||
|
Loading…
Reference in New Issue
Block a user