-
Notifications
You must be signed in to change notification settings - Fork 873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic jmh overhead test #3672
Changes from all commits
132b7a5
3ef6f63
653cf59
cdefb51
a508afd
6c42d16
e146a54
30f757a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar | ||
import me.champeau.jmh.JMHTask | ||
import net.ltgt.gradle.errorprone.errorprone | ||
|
||
plugins { | ||
id("otel.java-conventions") | ||
id("otel.jmh-conventions") | ||
} | ||
|
||
dependencies { | ||
jmhImplementation("org.springframework.boot:spring-boot-starter-web:2.5.2") | ||
jmhImplementation(project(":testing-common")) { | ||
exclude("ch.qos.logback") | ||
} | ||
|
||
// this only exists to make Intellij happy since it doesn't (currently at least) understand our | ||
// inclusion of this artifact inside of :testing-common | ||
jmhCompileOnly(project(path = ":testing:armeria-shaded-for-testing", configuration = "shadow")) | ||
} | ||
|
||
tasks { | ||
|
||
// TODO(trask) without disabling errorprone, jmh task fails with | ||
// Task :testing-overhead-jmh:jmhCompileGeneratedClasses FAILED | ||
// error: plug-in not found: ErrorProne | ||
withType<JavaCompile>().configureEach { | ||
options.errorprone { | ||
isEnabled.set(false) | ||
} | ||
} | ||
|
||
named<JMHTask>("jmh") { | ||
val shadowTask = project(":javaagent").tasks.named<ShadowJar>("shadowJar").get() | ||
inputs.files(layout.files(shadowTask)) | ||
|
||
// note: without an exporter, toSpanData() won't even be called | ||
// (which is good for benchmarking the instrumentation itself) | ||
val args = listOf( | ||
"-javaagent:${shadowTask.archiveFile.get()}", | ||
"-Dotel.traces.exporter=none", | ||
"-Dotel.metrics.exporter=none" | ||
) | ||
// see https://github.com/melix/jmh-gradle-plugin/issues/200 | ||
jvmArgsPrepend.add(args.joinToString(" ")) | ||
|
||
// TODO(trask) is this ok? if it's ok, move to otel.jmh-conventions? | ||
outputs.upToDateWhen { false } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.benchmark.servlet; | ||
|
||
import io.opentelemetry.javaagent.benchmark.servlet.app.HelloWorldApplication; | ||
import io.opentelemetry.testing.internal.armeria.client.WebClient; | ||
import java.util.concurrent.TimeUnit; | ||
import org.openjdk.jmh.annotations.Benchmark; | ||
import org.openjdk.jmh.annotations.BenchmarkMode; | ||
import org.openjdk.jmh.annotations.Mode; | ||
import org.openjdk.jmh.annotations.OutputTimeUnit; | ||
import org.openjdk.jmh.annotations.Scope; | ||
import org.openjdk.jmh.annotations.Setup; | ||
import org.openjdk.jmh.annotations.State; | ||
import org.openjdk.jmh.annotations.TearDown; | ||
|
||
@BenchmarkMode(Mode.SampleTime) | ||
@OutputTimeUnit(TimeUnit.MICROSECONDS) | ||
@State(Scope.Thread) | ||
public class ServletBenchmark { | ||
|
||
static { | ||
// using static initializer instead of @Setup since only want to initialize the app under test | ||
// once regardless of @State and @Threads | ||
HelloWorldApplication.main(); | ||
} | ||
|
||
// using shaded armeria http client from testing-common artifact since it won't be instrumented | ||
private WebClient client; | ||
|
||
@Setup | ||
public void setup() { | ||
client = WebClient.builder().build(); | ||
} | ||
|
||
@TearDown | ||
public void tearDown() { | ||
HelloWorldApplication.stop(); | ||
} | ||
|
||
@Benchmark | ||
public Object execute() { | ||
return client.get("http://localhost:8080").aggregate().join(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.benchmark.servlet; | ||
|
||
import org.openjdk.jmh.annotations.Fork; | ||
|
||
@Fork(jvmArgsAppend = "-Dotel.javaagent.enabled=false") | ||
public class ServletWithAgentDisabledBenchmark extends ServletBenchmark {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.benchmark.servlet; | ||
|
||
import org.openjdk.jmh.annotations.Fork; | ||
|
||
@Fork(jvmArgsAppend = "-Dotel.javaagent.experimental.use-noop-api=true") | ||
public class ServletWithNoopApiBenchmark extends ServletBenchmark {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.benchmark.servlet; | ||
|
||
import org.openjdk.jmh.annotations.Fork; | ||
|
||
@Fork(jvmArgsAppend = {"-Dotel.traces.sampler=traceidratio", "-Dotel.traces.sampler.arg=0.01"}) | ||
public class ServletWithOnePercentSamplingBenchmark extends ServletBenchmark {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.benchmark.servlet.app; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.context.ConfigurableApplicationContext; | ||
|
||
@SpringBootApplication | ||
public class HelloWorldApplication { | ||
|
||
private static volatile ConfigurableApplicationContext context; | ||
|
||
public static void main(String... args) { | ||
|
||
context = SpringApplication.run(HelloWorldApplication.class, args); | ||
} | ||
|
||
public static void stop() { | ||
context.stop(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.benchmark.servlet.app; | ||
|
||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class HelloWorldController { | ||
|
||
@GetMapping("/") | ||
public String root() { | ||
return "Hello world!"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
plugins { | ||
id("me.champeau.jmh") | ||
id("io.morethan.jmhreport") | ||
} | ||
|
||
dependencies { | ||
jmh(platform(project(":dependencyManagement"))) | ||
jmh("org.openjdk.jmh:jmh-core") | ||
jmh("org.openjdk.jmh:jmh-generator-bytecode") | ||
} | ||
|
||
// invoke jmh on a single benchmark class like so: | ||
// ./gradlew -PjmhIncludeSingleClass=StatsTraceContextBenchmark clean :grpc-core:jmh | ||
jmh { | ||
failOnError.set(true) | ||
resultFormat.set("JSON") | ||
// Otherwise an error will happen: | ||
// Could not expand ZIP 'byte-buddy-agent-1.9.7.jar'. | ||
includeTests.set(false) | ||
profilers.add("gc") | ||
val jmhIncludeSingleClass: String? by project | ||
if (jmhIncludeSingleClass != null) { | ||
includes.add(jmhIncludeSingleClass as String) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just curious: why this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC, the |
||
} | ||
} | ||
|
||
jmhReport { | ||
jmhResultPath = file("${buildDir}/results/jmh/results.json").absolutePath | ||
jmhReportOutput = file("${buildDir}/results/jmh").absolutePath | ||
} | ||
|
||
tasks { | ||
named("jmh") { | ||
finalizedBy(named("jmhReport")) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this file is identical copy from opentelemetry-java repo