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

Migrate Guava cache usage to Caffeine #295

Merged

Conversation

Stephan202
Copy link
Contributor

This PR is a replacement of #286, which was closed as a side effect of the deletion of its base branch. For the original context, see #258. This migration from Guava to Caffeine was unlocked by the migration to Java 8 in the context of #276.

I'll re-apply the comments from the other PR, so as to ease the review effort.

Copy link
Contributor Author

@Stephan202 Stephan202 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-applied the comments from #286.

@@ -17,7 +18,7 @@
* Return the value associated with the instance in this ExtensionHolder. If the value is not present it will be
* initialized (in a thread-safe manner) using valueLoader.
*/
public T getExtension(Object instance, Callable<T> valueLoader);
public T getExtension(Object instance, Supplier<T> valueLoader);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found only one implementation of this interface. If it is used elsewhere we should revert this change and introduce a try/catch construct in the implementation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep this change.

newrelic-agent/build.gradle Show resolved Hide resolved
activeTokens = CacheBuilder.newBuilder()
.concurrencyLevel(8)
activeTokens = Caffeine.newBuilder()
.initialCapacity(8)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context see the discussion @ #286 (comment). We should consider dropping this line.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are going to keep this change as is with capacity set to 8. I'm creating a research spike to unblock getting this merged and investigate whether resizing makes sense.

.expireAfterAccess(timeOutMilli, TimeUnit.MILLISECONDS)
.executor(Runnable::run)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Runnable::run is here because one of the tests expects to see the effects of the removal notification in a timely manner. See the wiki on how Caffeine may schedule this kind of work on another thread. Alternatively the test could be tweaked. If the current behavior is desired, perhaps .executor(Runnable::run) should also be added in AsyncTransactionService.

@@ -128,7 +128,7 @@ public ClassLoaderClassTransformer(InstrumentationProxy instrumentation, Set<Str
// Try to use a custom Guava-based extension template to make NewField access better
try {
extensionTemplate = WeaveUtils.convertToClassNode(WeaveUtils.getClassBytesFromClassLoaderResource(
GuavaBackedExtensionClass.class.getName(), GuavaBackedExtensionClass.class.getClassLoader()));
CaffeineBackedExtensionClass.class.getName(), CaffeineBackedExtensionClass.class.getClassLoader()));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GuavaBackedExtensionClass is now Caffeine-backend, so a rename seemed in order.

key,
k -> metricName == null
? sig.getMetricNameFormat(key.invocationTargetClassName, flags)
: new SimpleMetricNameFormat(getTracerMetricName(key.invocationTargetClassName, sig.getClassName(), metricName)));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the if condition is now only evaluated on cache misses.

// Make sure we pick up this Caffeine reference.
Caffeine<Object, Object> newBuilder = Caffeine.newBuilder();
// Make sure we pick up this Guava reference.
ImmutableSet<Object> set = ImmutableSet.of();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to my question above: no idea whether these test changes make sense.

@@ -239,7 +239,8 @@ public void testMaxInvalidClassLoaders() throws IOException {
wpm.weave(cl, "com/newrelic/weave/weavepackage/WeavePackageManagerTest$NewNoMatchClass",
WeaveTestUtils.getClassBytes("com.newrelic.weave.weavepackage.WeavePackageManagerTest$NewNoMatchClass"));
}
Assert.assertTrue(WeavePackageManager.MAX_INVALID_PACKAGE_CACHE >= wpm.invalidPackages.size());
wpm.invalidPackages.cleanUp();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the wiki; Caffeine's size-based eviction may cause the cache to grow slightly larger than configured. Here we trigger an explicit cleanup to make sure the test passes. Under normal operation this kind of cleanup is performed in the context of subsequent cache operations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one .cleanUp() call wasn't enough; added a commit with a more robust fix.

@XiXiaPdx
Copy link
Contributor

@Stephan202 Just a heads up that we are planning to review this after releasing agent version 7.0.0, which we are targeting for June 7th. Thank you for your contribution and patience!

@Stephan202
Copy link
Contributor Author

No hurry :)

For when the time comes: google/guava#5571 provides additional background.

@tbradellis
Copy link
Contributor

tbradellis commented Jun 2, 2021

@Stephan202 I've started doing some testing for this PR. I'm curious if this build resolves the deadlock we were seeing in the support ticket where discussing this change to Caffeine originally came up. Are you able to run this agent build in that environment?

@Stephan202
Copy link
Contributor Author

@tbradellis so far I did not attempt to deploy this code. Given our setup this wouldn't be impossible per se, but also a bit more work than I can commit to right now. I'll make a note in case I do find some spare time. 🤞

(For the time being we're still running with -Dnewrelic.config.class_transformer.com.newrelic.instrumentation.java.completable-future-jdk8u40.enabled=false. Haven't tried dropping it to see whether we're still hitting the issue in the first place. Will make a note to schedule such a test.)

@tbradellis
Copy link
Contributor

Hey @Stephan202 . I'm working to get this merged. I need to rebase and I also have a few minor changes for some of the comments.
Can you give permission on the fork for me to push changes?

@Stephan202
Copy link
Contributor Author

Hi @tbradellis. It turns out that the "Allow edits from maintainers" feature isn't available for PRs created from organization accounts (such as PicnicSupermarket). Instead I have invited you as an "outside collaborator" on the repository itself.

If you have any questions about this or the code, let me know. Tnx for picking this up!

@Stephan202 Stephan202 force-pushed the improvement/migrate-to-caffeine branch from 648f3c1 to c25ab73 Compare August 10, 2021 05:22
@Stephan202
Copy link
Contributor Author

I've rebased the branch on latest main; there were no conflicts.

W.r.t. open tasks, cursory inspection surfaces two more:

  • There are a few hits for git grep -i 'guava cache'; some/all of those should now probably reference Caffeine.
  • If THIRD_PARTY_NOTICES.md is manually maintained (seems so 👀) it should also be updated.

@Stephan202
Copy link
Contributor Author

It's not clear to me whether/how the Scala test failures relate to the changes in this PR.

@tbradellis
Copy link
Contributor

Scala test failures

We have an issue with out scala tests that we are working to fix. It's also a race condition so, once it reruns a few times it'll pass.

@CLAassistant
Copy link

CLAassistant commented Aug 17, 2021

CLA assistant check
All committers have signed the CLA.

@tbradellis
Copy link
Contributor

@Stephan202 It looks like I stepped on your commits when I had to --reset-author to get my license/cla accepted. I'll correct that.

@kford-newrelic
Copy link
Contributor

Hi @Stephan202 check your email when you have a moment (and your junk folder just in case) I tried to send you a message

@Stephan202 Stephan202 force-pushed the improvement/migrate-to-caffeine branch from 08997f0 to 7e82d80 Compare August 24, 2021 05:55
@Stephan202
Copy link
Contributor Author

@kford-newrelic it took me a while to find that email, as a GMail filter got hold of it; replied :)

@tbradellis I took the liberty to fix the author situation in this PR. (I still had an old version of the branch, so simply cherry-picked your commit on top of it and then rebased; there were no conflicts and the final diff is identical.)

@tbradellis tbradellis requested review from tbradellis and removed request for jasonjkeller and XiXiaPdx September 21, 2021 20:56
@tbradellis tbradellis closed this Sep 21, 2021
@tbradellis tbradellis reopened this Sep 21, 2021
@tbradellis tbradellis merged commit 015220c into newrelic:main Sep 21, 2021
@tbradellis tbradellis deleted the improvement/migrate-to-caffeine branch September 21, 2021 21:02
meiao added a commit that referenced this pull request Sep 24, 2021
…grate-to-caffeine"

This reverts commit 015220c, reversing
changes made to 0668807.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Consider Caffeine for Caching to Replace Guava After EOL of Java 7 Support
5 participants