Skip to content

Conversation

anuraaga
Copy link
Contributor

@anuraaga anuraaga commented Feb 20, 2021

The only remaining usage in the agent is caching, and there is usage at compile time by muzzle of the graph library and some test usage. So we'll be able to replace the caching with caffeine for a bit smaller distribution size and probably better cache performance.

@@ -489,8 +489,16 @@ public void onComplete(
@Override
public Iterable<Iterable<Class<?>>> resolve(Instrumentation instrumentation) {
// filter out our agent classes and injected helper classes
return Iterables.transform(
delegate.resolve(instrumentation), i -> Iterables.filter(i, c -> !isIgnored(c)));
return () ->
Copy link
Contributor

Choose a reason for hiding this comment

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

Hope you do understand this and tested it :) Looks like black magic to me

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Stream (single use) vs Iterable (multiuse) dilemma is always annoying. The safe way to convert a Stream into an Iterable is creating a Lambda that initializes the Stream and returns the iterator, which is what an Iterable is.

The alternative is to collect(toList) each time which I'm ok with but I don't know this part well enough to know if the extra allocations would be problematic.

Copy link
Member

Choose a reason for hiding this comment

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

I think naming the Iterable <-> Stream transformations makes it (a bit) easier to read:

    public Iterable<Iterable<Class<?>>> resolve(Instrumentation instrumentation) {
      // filter out our agent classes and injected helper classes
      return iterableOf(
          streamOf(delegate.resolve(instrumentation))
              .map(classes -> iterableOf(streamOf(classes).filter(c -> !isIgnored(c)))));
    }

    private static <E> Stream<E> streamOf(Iterable<E> iterable) {
      return StreamSupport.stream(iterable.spliterator(), false);
    }

    private static <E> Iterable<E> iterableOf(Stream<E> stream) {
      return stream::iterator;
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately stream:: iterator isn't a real Iterable since it can't be replayed, so toIterable would need to accept Supplier<Stream>. Not sure if that ends up better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tried, how is it?

Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately stream:: iterator isn't a real Iterable since it can't be replayed

😭

ok, how about

    public Iterable<Iterable<Class<?>>> resolve(Instrumentation instrumentation) {
      // filter out our agent classes and injected helper classes
      return () -> streamOf(delegate.resolve(instrumentation)).map(this::filterClasses).iterator();
    }

    private Iterable<Class<?>> filterClasses(Iterable<Class<?>> classes) {
      return () -> streamOf(classes).filter(c -> !isIgnored(c)).iterator();
    }

    private static <T> Stream<T> streamOf(Iterable<T> iterable) {
      return StreamSupport.stream(iterable.spliterator(), false);
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure seems good

@@ -489,8 +489,16 @@ public void onComplete(
@Override
public Iterable<Iterable<Class<?>>> resolve(Instrumentation instrumentation) {
// filter out our agent classes and injected helper classes
return Iterables.transform(
delegate.resolve(instrumentation), i -> Iterables.filter(i, c -> !isIgnored(c)));
return () ->
Copy link
Member

Choose a reason for hiding this comment

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

I think naming the Iterable <-> Stream transformations makes it (a bit) easier to read:

    public Iterable<Iterable<Class<?>>> resolve(Instrumentation instrumentation) {
      // filter out our agent classes and injected helper classes
      return iterableOf(
          streamOf(delegate.resolve(instrumentation))
              .map(classes -> iterableOf(streamOf(classes).filter(c -> !isIgnored(c)))));
    }

    private static <E> Stream<E> streamOf(Iterable<E> iterable) {
      return StreamSupport.stream(iterable.spliterator(), false);
    }

    private static <E> Iterable<E> iterableOf(Stream<E> stream) {
      return stream::iterator;
    }

@anuraaga anuraaga merged commit 2244377 into open-telemetry:main Feb 22, 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.

3 participants