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

[Skylark] Move method invocation logic to MethodDescriptor. #5704

Closed
wants to merge 7 commits into from

Conversation

ttsugriy
Copy link
Contributor

This serves 2 purposes:

  • better encapsulation and domain model.
  • opens the door to optimizations like using MethodHandle instead of Method
    and caching.
  • performs one of the optimizations mentioned above - perform setAccessible
    only once instead of on every method invocation. JMH suggests that this saves
    ~5% of CPU time.

Next steps are:

  • evaluate peformance improvements for some of the optimizations listed above
  • make PRs to apply optimizations that seem beneficial.

Java uses dynamically generated proxy classes to access annotation properties
and their methods are ~7X slower than plain getters. According to async-profiler
50%+ of `convertArgumentList` method time is spent in dynamic proxy methods, so
optimizing their performance makes sense.

This also makes the model less anemic, since POJOs can actually provide business
methods.
This change is focused on 2 things:
- avoid creating builders in case they don't end up being used
- create builders using the maximum expected size to avoid intermediate
  allocations to accomodate more elements
Java uses dynamically generated proxy classes to access annotation properties
and their methods are ~7X slower than plain getters. According to async-profiler
50%+ of `convertArgumentList` method time is spent in dynamic proxy methods, so
optimizing their performance makes sense.

This also makes the model less anemic, since POJOs can actually provide business
methods.
According to async-profiler, about 50% of `Tuple.getSlice` method
invocation is spent in `ImmutableList.copyOf` which is completely
unnecessary for cases when an `ImmutableList` instance is passed.
When `isLegacyNamed` is `true`, `named` is considered to be `true` as well,
so instead of going through an extra indirection and computation, just use
`named` field to store combined result.
This serves 2 purposes:
- better encapsulation and domain model.
- opens the door to optimizations like using `MethodHandle` instead of `Method`
  and caching.
- performs one of the optimizations mentioned above - perform `setAccessible`
  only once instead of on every method invocation. JMH suggests that this saves
  ~5% of CPU time.

Next steps are:
- evaluate peformance improvements for some of the optimizations listed above
- make PRs to apply optimizations that seem beneficial.
@ttsugriy
Copy link
Contributor Author

rebased and resolved conflicts

@@ -54,8 +53,7 @@ private ParamDescriptor(
this.allowedTypes = allowedTypes;
Copy link
Contributor

Choose a reason for hiding this comment

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

side-note (unrelated to this PR): arguments callbackEnabled and doc are unused

Copy link
Contributor

@laurentlb laurentlb left a comment

Choose a reason for hiding this comment

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

Looks great!

@bazel-io bazel-io closed this in 6e7fae1 Jul 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants