Skip to content
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

KAFKA-12357: Do not inline methods from the scala package by default #10174

Merged
merged 1 commit into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ The following options should be set with a `-P` switch, for example `./gradlew -
* `enableTestCoverage`: enables test coverage plugins and tasks, including bytecode enhancement of classes required to track said
coverage. Note that this introduces some overhead when running tests and hence why it's disabled by default (the overhead
varies, but 15-20% is a reasonable estimate).
* `scalaOptimizerMode`: configures the optimizing behavior of the scala compiler, the value should be one of `none`, `method`, `inline-kafka` or
`inline-scala` (the default is `inline-kafka`). `none` is the scala compiler default, which only eliminates unreachable code. `method` also
includes method-local optimizations. `inline-kafka` adds inlining of methods within the kafka packages. Finally, `inline-scala` also
includes inlining of methods within the scala library (which avoids lambda allocations for methods like `Option.exists`). `inline-scala` is
only safe if the Scala library version is the same at compile time and runtime. Since we cannot guarantee this for all cases (for example, users
may depend on the kafka jar for integration tests where they may include a scala library with a different version), we don't enable it by
default. See https://www.lightbend.com/blog/scala-inliner-optimizer for more details.

### Dependency Analysis ###

Expand Down
32 changes: 18 additions & 14 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ ext {

userEnableTestCoverage = project.hasProperty("enableTestCoverage") ? enableTestCoverage : false

// See README.md for details on this option and the reasoning for the default
userScalaOptimizerMode = project.hasProperty("scalaOptimizerMode") ? scalaOptimizerMode : "inline-kafka"
def scalaOptimizerValues = ["none", "method", "inline-kafka", "inline-scala"]
if (!scalaOptimizerValues.contains(userScalaOptimizerMode))
throw new GradleException("Unexpected value for scalaOptimizerMode property. Expected one of $scalaOptimizerValues), but received: $userScalaOptimizerMode")

generatedDocsDir = new File("${project.rootDir}/docs/generated")

commitId = project.hasProperty('commitId') ? commitId : null
Expand Down Expand Up @@ -515,21 +521,19 @@ subprojects {
"-Xlint:unused"
]

// Inline more aggressively when compiling the `core` jar since it's not meant to be used as a library.
// More specifically, inline classes from the Scala library so that we can inline methods like `Option.exists`
// and avoid lambda allocations. This is only safe if the Scala library version is the same at compile time
// and runtime. We cannot guarantee this for libraries like kafka streams, so only inline classes from the
// Kafka project in that case.
List<String> inlineFrom
if (project.name.equals('core'))
inlineFrom = ["-opt-inline-from:scala.**", "-opt-inline-from:kafka.**", "-opt-inline-from:org.apache.kafka.**"]
else
inlineFrom = ["-opt-inline-from:org.apache.kafka.**"]
// See README.md for details on this option and the meaning of each value
if (userScalaOptimizerMode.equals("method"))
scalaCompileOptions.additionalParameters += ["-opt:l:method"]
else if (userScalaOptimizerMode.startsWith("inline-")) {
List<String> inlineFrom = ["-opt-inline-from:org.apache.kafka.**"]
if (project.name.equals('core'))
inlineFrom.add("-opt-inline-from:kafka.**")
if (userScalaOptimizerMode.equals("inline-scala"))
inlineFrom.add("-opt-inline-from:scala.**")

// Somewhat confusingly, `-opt:l:inline` enables all optimizations. `inlineFrom` configures what can be inlined.
// See https://www.lightbend.com/blog/scala-inliner-optimizer for more information about the optimizer.
scalaCompileOptions.additionalParameters += ["-opt:l:inline"]
scalaCompileOptions.additionalParameters += inlineFrom
scalaCompileOptions.additionalParameters += ["-opt:l:inline"]
scalaCompileOptions.additionalParameters += inlineFrom
}

if (versions.baseScala != '2.12') {
scalaCompileOptions.additionalParameters += ["-opt-warnings", "-Xlint:strict-unsealed-patmat"]
Expand Down