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

Add a caching API based on caffeine for use from instrumentation, not just javaagent #2477

Merged
merged 12 commits into from Mar 5, 2021

Conversation

anuraaga
Copy link
Contributor

@anuraaga anuraaga commented Mar 3, 2021

For now just adds the most minimal API, computeIfAbsent.

@anuraaga
Copy link
Contributor Author

anuraaga commented Mar 3, 2021

@ben-manes After I experimented with gradle-shadow-plugin's minimization feature, I found that it's only about a 350K dependency to add caffeine for our purposes, so we're going with it instead of the concurrentlinkedhashmap. If you have a chance to skim this to see if it's a sane approach, that would be much appreciated.

});
assertThat(cache.computeIfAbsent(dog, unused -> "bark")).isEqualTo("bark");
dog = null;
System.gc();

Choose a reason for hiding this comment

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

GcFinalizable from guava testlib is great for this as more predictable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the hint! I've always wondered about this but in practice have yet to see a failure due to only calling gc once and continue with this pattern. Looking at it

https://github.com/google/guava/blob/master/guava-testlib/src/com/google/common/testing/GcFinalization.java#L186

I feel as if it would be mostly the same to move System.gc into the await() predicate, possibly tweaking the polling interval, which is nice to reduce the number of ways of doing something. Might do one or the other if this flakes in the future.

@ben-manes
Copy link

That’s great!

Anuraag Agrawal added 2 commits March 3, 2021 18:02
}
jar {
from(sourceSets.patch.output) {
include 'com/github/benmanes/caffeine/cache/BoundedLocalCache$PerformCleanupTask.class'
Copy link
Member

Choose a reason for hiding this comment

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

Will this file be shaded too? Also, why javaagent-bootstrap and not the new module?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh good catch, I don't think this is doing anything because of the non shading (I'll need to come up with a bespoke test for this I guess). It's here since only the agent cares, not library instrumentation.

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 additional reference there is a gap here vs datadog - they keep Caffeine in the agent classloader but we are shading and putting in the bootstrap classloader instead to allow the same instrumentation to work for both library and agent.

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 fixed the package name but couldn't come up with a way to add a test for this. Anyone have any ideas?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was able to come up with a test, a bit annoying since I need a different Gradle project to be able to check the patched jar itself.

Comment on lines +32 to +34
@SuppressWarnings("unchecked")
com.github.benmanes.caffeine.cache.Cache<K, V> delegate =
(com.github.benmanes.caffeine.cache.Cache<K, V>) caffeine.build();
Copy link
Member

Choose a reason for hiding this comment

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

Why not add <K, V> as type parameters of CacheBuilder?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah Caffeine has them - since we don't have loading cache at least for now I couldn't find a reason to have them on the builder. This is the same trick Caffeine uses to convert Caffeine<Object, Object> to Cache<K, V>.

assertThat(caffeineCache.keySet()).hasSize(1);

assertThat(cache.computeIfAbsent("dog", unused -> "bark")).isEqualTo("bark");
caffeineCache.cleanup();
Copy link
Member

Choose a reason for hiding this comment

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

Just wondering: what does cleanup() exactly do here, does it remove values over max size?
Does this test pass without it? Would adding it to unbounded() make that test fail?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup it ensures values over max are removed since Caffeine does that asynchronously. Without it out fails, but for non evictions it's not needed

Choose a reason for hiding this comment

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

If you prefer, set the executor to Runnable::run for a direct call. The async isn’t needed for the cache’s own maintenance as that is fast, but we have optional callbacks to user code so it’s protected if that is slow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ben-manes Thanks for the tip! Going to leave it as is for now to use the defaults as a baseline. Will set up a simple benchmark for our own sanity checking later, compare the two, and then pick one.

Copy link
Member

@mateuszrzeszutek mateuszrzeszutek left a comment

Choose a reason for hiding this comment

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

Nice! 🎉

Copy link
Member

@trask trask left a comment

Choose a reason for hiding this comment

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

nice 👍

@anuraaga anuraaga merged commit d7f8967 into open-telemetry:main Mar 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants