Skip to content

Commit

Permalink
Use caffeine3 on jdk11 and caffeine2 on older jdks (#4154)
Browse files Browse the repository at this point in the history
* Use caffeine3 on jdk11 and caffein2 on older jdks

* ignore caffeine3 classes on java 8

* Update dependencyManagement/build.gradle.kts

Co-authored-by: Mateusz Rzeszutek <mrzeszutek@splunk.com>

Co-authored-by: Mateusz Rzeszutek <mrzeszutek@splunk.com>
  • Loading branch information
laurit and Mateusz Rzeszutek authored Sep 21, 2021
1 parent a8b6faf commit 8c8eb3d
Show file tree
Hide file tree
Showing 15 changed files with 436 additions and 58 deletions.
4 changes: 3 additions & 1 deletion benchmark/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ plugins {
id("otel.jmh-conventions")
}

val caffeine2Version: String by project

dependencies {
jmh(platform(project(":dependencyManagement")))

Expand All @@ -19,7 +21,7 @@ dependencies {
jmh(project(":javaagent-tooling"))
jmh(project(":javaagent-extension-api"))

jmh("com.github.ben-manes.caffeine:caffeine")
jmh("com.github.ben-manes.caffeine:caffeine:$caffeine2Version")

jmh("javax.servlet:javax.servlet-api:4.0.1")
jmh("com.google.http-client:google-http-client:1.19.0")
Expand Down
4 changes: 3 additions & 1 deletion dependencyManagement/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ rootProject.extra["otelVersion"] = otelVersion
// Need both BOM and -all
val groovyVersion = "2.5.11"

rootProject.extra["caffeine2Version"] = "2.9.2"
rootProject.extra["caffeine3Version"] = "3.0.4"

// We don't force libraries we instrument to new versions since we compile and test against specific
// old baseline versions
// but we do try to force those libraries' transitive dependencies to new versions where possible
Expand Down Expand Up @@ -85,7 +88,6 @@ val DEPENDENCY_SETS = listOf(
val DEPENDENCIES = listOf(
"ch.qos.logback:logback-classic:1.2.3",
"com.blogspot.mydailyjava:weak-lock-free:0.18",
"com.github.ben-manes.caffeine:caffeine:2.9.0",
"com.github.stefanbirkner:system-lambda:1.2.0",
"com.github.stefanbirkner:system-rules:1.19.0",
"com.google.auto.service:auto-service:1.0",
Expand Down
35 changes: 13 additions & 22 deletions instrumentation-api-caching/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,41 @@ plugins {
id("otel.java-conventions")
}

sourceSets {
main {
val caffeine2ShadedDeps = project(":instrumentation-api-caching:caffeine2")
output.dir(caffeine2ShadedDeps.file("build/extracted/shadow"), "builtBy" to ":instrumentation-api-caching:caffeine2:extractShadowJar")

val caffeine3ShadedDeps = project(":instrumentation-api-caching:caffeine3")
output.dir(caffeine3ShadedDeps.file("build/extracted/shadow"), "builtBy" to ":instrumentation-api-caching:caffeine3:extractShadowJar")
}
}

val shadowInclude by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
}

dependencies {
compileOnly("com.github.ben-manes.caffeine:caffeine")
shadowInclude("com.github.ben-manes.caffeine:caffeine") {
exclude("com.google.errorprone", "error_prone_annotations")
exclude("org.checkerframework", "checker-qual")
}
compileOnly(project(":instrumentation-api-caching:caffeine2", configuration = "shadow"))
compileOnly(project(":instrumentation-api-caching:caffeine3", configuration = "shadow"))

compileOnly("com.blogspot.mydailyjava:weak-lock-free")
shadowInclude("com.blogspot.mydailyjava:weak-lock-free")
}

// patch inner class from Caffeine to avoid ForkJoinTask from being loaded too early in the javaagent
val patch by sourceSets.creating {
java {}
}

tasks {
shadowJar {
configurations = listOf(shadowInclude)

relocate("com.github.benmanes.caffeine", "io.opentelemetry.instrumentation.api.internal.shaded.caffeine")
relocate("com.blogspot.mydailyjava.weaklockfree", "io.opentelemetry.instrumentation.api.internal.shaded.weaklockfree")

minimize()
}

val extractShadowJar by registering(Copy::class) {
dependsOn(shadowJar)

// replace caffeine class with our patched version
from(zipTree(shadowJar.get().archiveFile)) {
exclude("io/opentelemetry/instrumentation/api/internal/shaded/caffeine/cache/BoundedLocalCache\$PerformCleanupTask.class")
exclude("META-INF/**")
}
from(patch.output) {
include("io/opentelemetry/instrumentation/api/internal/shaded/caffeine/cache/BoundedLocalCache\$PerformCleanupTask.class")
}

into("build/extracted/shadow")
// prevents empty com/github/benmanes/caffeine/cache path from ending up in instrumentation-api
includeEmptyDirs = false
}
}
56 changes: 56 additions & 0 deletions instrumentation-api-caching/caffeine2/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
plugins {
id("com.github.johnrengelman.shadow")

id("otel.java-conventions")
}

val shadowInclude by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
}

val caffeine2Version: String by project

dependencies {
compileOnly("com.github.ben-manes.caffeine:caffeine:$caffeine2Version")
shadowInclude("com.github.ben-manes.caffeine:caffeine:$caffeine2Version") {
exclude("com.google.errorprone", "error_prone_annotations")
exclude("org.checkerframework", "checker-qual")
}
}

// patch inner class from Caffeine to avoid ForkJoinTask from being loaded too early in the javaagent
val patch by sourceSets.creating {
java {}
}

tasks {
shadowJar {
configurations = listOf(shadowInclude)

relocate("com.github.benmanes.caffeine", "io.opentelemetry.instrumentation.api.internal.shaded.caffeine2")

minimize()
}

javadoc {
enabled = false
}

val extractShadowJar by registering(Copy::class) {
dependsOn(shadowJar)

// replace caffeine class with our patched version
from(zipTree(shadowJar.get().archiveFile)) {
exclude("io/opentelemetry/instrumentation/api/internal/shaded/caffeine2/cache/BoundedLocalCache\$PerformCleanupTask.class")
exclude("META-INF/**")
}
from(patch.output) {
include("io/opentelemetry/instrumentation/api/internal/shaded/caffeine2/cache/BoundedLocalCache\$PerformCleanupTask.class")
}

into("build/extracted/shadow")
// prevents empty com/github/benmanes/caffeine/cache path from ending up in instrumentation-api
includeEmptyDirs = false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
* limitations under the License.
*/

package io.opentelemetry.instrumentation.api.internal.shaded.caffeine.cache;
package io.opentelemetry.instrumentation.api.internal.shaded.caffeine2.cache;

import java.lang.ref.WeakReference;

Expand Down
56 changes: 56 additions & 0 deletions instrumentation-api-caching/caffeine3/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
plugins {
id("com.github.johnrengelman.shadow")

id("otel.java-conventions")
}

val shadowInclude by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
}

val caffeine3Version: String by project

dependencies {
compileOnly("com.github.ben-manes.caffeine:caffeine:$caffeine3Version")
shadowInclude("com.github.ben-manes.caffeine:caffeine:$caffeine3Version") {
exclude("com.google.errorprone", "error_prone_annotations")
exclude("org.checkerframework", "checker-qual")
}
}

// patch inner class from Caffeine to avoid ForkJoinTask from being loaded too early in the javaagent
val patch by sourceSets.creating {
java {}
}

tasks {
shadowJar {
configurations = listOf(shadowInclude)

relocate("com.github.benmanes.caffeine", "io.opentelemetry.instrumentation.api.internal.shaded.caffeine3")

minimize()
}

javadoc {
enabled = false
}

val extractShadowJar by registering(Copy::class) {
dependsOn(shadowJar)

// replace caffeine class with our patched version
from(zipTree(shadowJar.get().archiveFile)) {
exclude("io/opentelemetry/instrumentation/api/internal/shaded/caffeine3/cache/BoundedLocalCache\$PerformCleanupTask.class")
exclude("META-INF/**")
}
from(patch.output) {
include("io/opentelemetry/instrumentation/api/internal/shaded/caffeine3/cache/BoundedLocalCache\$PerformCleanupTask.class")
}

into("build/extracted/shadow")
// prevents empty com/github/benmanes/caffeine/cache path from ending up in instrumentation-api
includeEmptyDirs = false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package com.github.benmanes.caffeine.cache;

// Caffeine uses reflection to load cache implementations based on parameters specified by a user.
// We use gradle-shadow-plugin to minimize the dependency on Caffeine, but it does not allow
// specifying classes to keep, only artifacts. It's a relatively simple workaround for us to use
// this non-public class to create a static link to the required implementations we use.
final class CacheImplementations {

// Each type of cache has a cache implementation and a node implementation.

// Strong keys, strong values, maximum size
SSMS<?, ?> ssms; // cache
PSMS<?, ?> psms; // node

// Weak keys, strong values, maximum size
WSMS<?, ?> wsms; // cache
FSMS<?, ?> fsms; // node

// Weak keys, weak values
WI<?, ?> wi; // cache
FW<?, ?> fw; // node

private CacheImplementations() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

// Includes work from:
/*
* Copyright 2017 Datadog, Inc.
*
* 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.
*/
/*
* Copyright 2014 Ben Manes. All Rights Reserved.
*
* 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.opentelemetry.instrumentation.api.internal.shaded.caffeine3.cache;

import java.lang.ref.WeakReference;

/** skeleton outer class just for compilation purposes, not included in the final patch. */
abstract class BoundedLocalCache<K, V> {
abstract void performCleanUp(Runnable task);

/** patched to not extend ForkJoinTask as we don't want that class loaded too early. */
static final class PerformCleanupTask implements Runnable {
private static final long serialVersionUID = 1L;

final WeakReference<BoundedLocalCache<?, ?>> reference;

PerformCleanupTask(BoundedLocalCache<?, ?> cache) {
reference = new WeakReference<>(cache);
}

@Override
public void run() {
BoundedLocalCache<?, ?> cache = reference.get();
if (cache != null) {
cache.performCleanUp(/* ignored */ null);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

package io.opentelemetry.instrumentation.api.caching;

import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.Executor;
import org.checkerframework.checker.nullness.qual.Nullable;

/** A builder of {@link Cache}. */
public final class CacheBuilder {

private static final long UNSET = -1;
private static final boolean USE_CAFFEINE_3 = Caffeine3Cache.available();

private boolean weakKeys;
private boolean weakValues;
Expand Down Expand Up @@ -51,7 +51,8 @@ public <K, V> Cache<K, V> build() {
if (weakKeys && !weakValues && maximumSize == UNSET) {
return new WeakLockFreeCache<>();
}
Caffeine<?, ?> caffeine = Caffeine.newBuilder();
CaffeineCache.Builder<K, V> caffeine =
USE_CAFFEINE_3 ? new Caffeine3Cache.Builder<>() : new Caffeine2Cache.Builder<>();
if (weakKeys) {
caffeine.weakKeys();
}
Expand All @@ -66,10 +67,7 @@ public <K, V> Cache<K, V> build() {
} else {
caffeine.executor(Runnable::run);
}
@SuppressWarnings("unchecked")
com.github.benmanes.caffeine.cache.Cache<K, V> delegate =
(com.github.benmanes.caffeine.cache.Cache<K, V>) caffeine.build();
return new CaffeineCache<>(delegate);
return caffeine.build();
}

CacheBuilder() {}
Expand Down
Loading

0 comments on commit 8c8eb3d

Please sign in to comment.