Overhead benchmarks: Perform a warmup phase. (#3815)
* perform a warmup phase. * simplify approach to starting JFR recording. * remove JMX * use liberica jvm
This commit is contained in:
parent
392fc5a6c1
commit
44b71b77e1
|
@ -11,8 +11,7 @@ WORKDIR /app/spring-petclinic-rest
|
||||||
RUN ./mvnw package -Dmaven.test.skip=true
|
RUN ./mvnw package -Dmaven.test.skip=true
|
||||||
RUN cp target/spring-petclinic-rest*.jar /app/spring-petclinic-rest.jar
|
RUN cp target/spring-petclinic-rest*.jar /app/spring-petclinic-rest.jar
|
||||||
|
|
||||||
FROM adoptopenjdk:11-jre
|
FROM bellsoft/liberica-openjdk-alpine:11
|
||||||
|
|
||||||
COPY --from=app-build /app/spring-petclinic-rest.jar /app/spring-petclinic-rest.jar
|
COPY --from=app-build /app/spring-petclinic-rest.jar /app/spring-petclinic-rest.jar
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 9966
|
EXPOSE 9966
|
||||||
|
|
|
@ -30,6 +30,9 @@ import org.junit.jupiter.api.DynamicTest;
|
||||||
import org.junit.jupiter.api.TestFactory;
|
import org.junit.jupiter.api.TestFactory;
|
||||||
import org.testcontainers.containers.GenericContainer;
|
import org.testcontainers.containers.GenericContainer;
|
||||||
import org.testcontainers.containers.Network;
|
import org.testcontainers.containers.Network;
|
||||||
|
import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy;
|
||||||
|
import org.testcontainers.utility.DockerImageName;
|
||||||
|
import org.testcontainers.utility.MountableFile;
|
||||||
|
|
||||||
public class OverheadTests {
|
public class OverheadTests {
|
||||||
|
|
||||||
|
@ -76,6 +79,12 @@ public class OverheadTests {
|
||||||
petclinic.start();
|
petclinic.start();
|
||||||
writeStartupTimeFile(agent, start);
|
writeStartupTimeFile(agent, start);
|
||||||
|
|
||||||
|
if(config.getWarmupSeconds() > 0){
|
||||||
|
doWarmupPhase(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
startRecording(agent, petclinic);
|
||||||
|
|
||||||
GenericContainer<?> k6 = new K6Container(NETWORK, agent, config, namingConventions).build();
|
GenericContainer<?> k6 = new K6Container(NETWORK, agent, config, namingConventions).build();
|
||||||
k6.start();
|
k6.start();
|
||||||
|
|
||||||
|
@ -88,6 +97,28 @@ public class OverheadTests {
|
||||||
postgres.stop();
|
postgres.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startRecording(Agent agent, GenericContainer<?> petclinic) throws Exception {
|
||||||
|
Path outFile = namingConventions.container.jfrFile(agent);
|
||||||
|
String[] command = {"jcmd", "1", "JFR.start", "settings=profile", "dumponexit=true", "name=petclinic", "filename=" + outFile};
|
||||||
|
petclinic.execInContainer(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doWarmupPhase(TestConfig testConfig) {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
System.out.println("Performing startup warming phase for " + testConfig.getWarmupSeconds() + " seconds...");
|
||||||
|
while(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - start) < testConfig.getWarmupSeconds()){
|
||||||
|
GenericContainer<?> k6 = new GenericContainer<>(
|
||||||
|
DockerImageName.parse("loadimpact/k6"))
|
||||||
|
.withNetwork(NETWORK)
|
||||||
|
.withCopyFileToContainer(
|
||||||
|
MountableFile.forHostPath("./k6"), "/app")
|
||||||
|
.withCommand("run", "-u", "5", "-i", "25", "/app/basic.js")
|
||||||
|
.withStartupCheckStrategy(new OneShotStartupCheckStrategy());
|
||||||
|
k6.start();
|
||||||
|
}
|
||||||
|
System.out.println("Warmup complete.");
|
||||||
|
}
|
||||||
|
|
||||||
private void writeStartupTimeFile(Agent agent, long start) throws IOException {
|
private void writeStartupTimeFile(Agent agent, long start) throws IOException {
|
||||||
long delta = System.currentTimeMillis() - start;
|
long delta = System.currentTimeMillis() - start;
|
||||||
Path startupPath = namingConventions.local.startupDurationFile(agent);
|
Path startupPath = namingConventions.local.startupDurationFile(agent);
|
||||||
|
|
|
@ -17,18 +17,21 @@ public enum Configs {
|
||||||
.name("release")
|
.name("release")
|
||||||
.description("compares the latest stable release to no agent")
|
.description("compares the latest stable release to no agent")
|
||||||
.withAgents(Agent.NONE, Agent.LATEST_RELEASE)
|
.withAgents(Agent.NONE, Agent.LATEST_RELEASE)
|
||||||
|
.warmupSeconds(30)
|
||||||
.build()
|
.build()
|
||||||
),
|
),
|
||||||
SNAPSHOT(TestConfig.builder()
|
SNAPSHOT(TestConfig.builder()
|
||||||
.name("snapshot")
|
.name("snapshot")
|
||||||
.description("compares the latest snapshot to no agent")
|
.description("compares the latest snapshot to no agent")
|
||||||
.withAgents(Agent.NONE, Agent.LATEST_SNAPSHOT)
|
.withAgents(Agent.NONE, Agent.LATEST_SNAPSHOT)
|
||||||
|
.warmupSeconds(30)
|
||||||
.build()
|
.build()
|
||||||
),
|
),
|
||||||
SNAPSHOT_REGRESSION(TestConfig.builder()
|
SNAPSHOT_REGRESSION(TestConfig.builder()
|
||||||
.name("snapshot-regression")
|
.name("snapshot-regression")
|
||||||
.description("compares the latest snapshot to the latest stable release")
|
.description("compares the latest snapshot to the latest stable release")
|
||||||
.withAgents(Agent.LATEST_RELEASE, Agent.LATEST_SNAPSHOT)
|
.withAgents(Agent.LATEST_RELEASE, Agent.LATEST_SNAPSHOT)
|
||||||
|
.warmupSeconds(30)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class TestConfig {
|
||||||
|
|
||||||
private final static int DEFAULT_MAX_REQUEST_RATE = 0; // none
|
private final static int DEFAULT_MAX_REQUEST_RATE = 0; // none
|
||||||
private final static int DEFAULT_CONCURRENT_CONNECTIONS = 5;
|
private final static int DEFAULT_CONCURRENT_CONNECTIONS = 5;
|
||||||
private final static int DEFAULT_TOTAL_ITERATIONS = 500;
|
private final static int DEFAULT_TOTAL_ITERATIONS = 5000;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
@ -25,6 +25,7 @@ public class TestConfig {
|
||||||
private final int maxRequestRate;
|
private final int maxRequestRate;
|
||||||
private final int concurrentConnections;
|
private final int concurrentConnections;
|
||||||
private final int totalIterations;
|
private final int totalIterations;
|
||||||
|
private final int warmupSeconds;
|
||||||
|
|
||||||
public TestConfig(Builder builder) {
|
public TestConfig(Builder builder) {
|
||||||
this.name = builder.name;
|
this.name = builder.name;
|
||||||
|
@ -33,6 +34,7 @@ public class TestConfig {
|
||||||
this.maxRequestRate = builder.maxRequestRate;
|
this.maxRequestRate = builder.maxRequestRate;
|
||||||
this.concurrentConnections = builder.concurrentConnections;
|
this.concurrentConnections = builder.concurrentConnections;
|
||||||
this.totalIterations = builder.totalIterations;
|
this.totalIterations = builder.totalIterations;
|
||||||
|
this.warmupSeconds = builder.warmupSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@ -59,7 +61,11 @@ public class TestConfig {
|
||||||
return totalIterations;
|
return totalIterations;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Builder builder() {
|
public int getWarmupSeconds() {
|
||||||
|
return warmupSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +76,7 @@ public class TestConfig {
|
||||||
private int maxRequestRate = DEFAULT_MAX_REQUEST_RATE;
|
private int maxRequestRate = DEFAULT_MAX_REQUEST_RATE;
|
||||||
private int concurrentConnections = DEFAULT_CONCURRENT_CONNECTIONS;
|
private int concurrentConnections = DEFAULT_CONCURRENT_CONNECTIONS;
|
||||||
private int totalIterations = DEFAULT_TOTAL_ITERATIONS;
|
private int totalIterations = DEFAULT_TOTAL_ITERATIONS;
|
||||||
|
public int warmupSeconds = 0;
|
||||||
|
|
||||||
Builder name(String name) {
|
Builder name(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -101,6 +108,11 @@ public class TestConfig {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Builder warmupSeconds(int warmupSeconds){
|
||||||
|
this.warmupSeconds = warmupSeconds;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
TestConfig build(){
|
TestConfig build(){
|
||||||
return new TestConfig(this);
|
return new TestConfig(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,11 +71,8 @@ public class PetClinicRestContainer {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String[] buildCommandline(Optional<Path> agentJar) {
|
private String[] buildCommandline(Optional<Path> agentJar) {
|
||||||
Path jfrFile = namingConventions.container.jfrFile(this.agent);
|
|
||||||
List<String> result = new ArrayList<>(Arrays.asList(
|
List<String> result = new ArrayList<>(Arrays.asList(
|
||||||
"java",
|
"java",
|
||||||
"-XX:StartFlightRecording:dumponexit=true,disk=true,settings=profile,name=petclinic,filename="
|
|
||||||
+ jfrFile,
|
|
||||||
"-Dotel.traces.exporter=otlp",
|
"-Dotel.traces.exporter=otlp",
|
||||||
"-Dotel.imr.export.interval=5000",
|
"-Dotel.imr.export.interval=5000",
|
||||||
"-Dotel.exporter.otlp.insecure=true",
|
"-Dotel.exporter.otlp.insecure=true",
|
||||||
|
|
Loading…
Reference in New Issue