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

[Performance] Use invoke dynamic instead of Method.invoke for @Exported #96

Merged
merged 1 commit into from
Jan 14, 2017

Conversation

i386
Copy link
Contributor

@i386 i386 commented Dec 29, 2016

Use invoke dynamic (MethodHandles) instead of Method.invoke for @exported.

MethodHandles seem to be what all the cool serialisers like protobuf use for performance reasons. This means that Stapler has to require JDK 7 minimum.

Initial testing seemed to show I could shave 20% off of the time to serve some Blue Ocean rest calls.

@i386 i386 changed the title Use invoke dynamic instead of Method.invoke for @Exported and cache m… [Performance] Use invoke dynamic instead of Method.invoke for @Exported Dec 29, 2016
@i386
Copy link
Contributor Author

i386 commented Jan 1, 2017

PTAL @vivek

@@ -13,7 +13,7 @@ pipeline {
}
}

postBuild {
post {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unrelated change to make CI pass. Needs #93 to be merged.

return METHOD_HANDLES.getUnchecked(method);
}

private static final LoadingCache<Method, MethodHandle> METHOD_HANDLES = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.HOURS).build(new CacheLoader<Method, MethodHandle>() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe configurable number of cache expiry hours, maybe a system property?

@vivek
Copy link
Contributor

vivek commented Jan 4, 2017

@i386 It's surprising to see this kind of perf gain just by switch to invokedynamic based invocation. these are pretty basic method invocation (no duck typing involved really, unless we are talking about groovy or jruby like working with duck typing). Or maybe its the cache doing the perf gain as compared to invoke dynamic? IOW did you try comparing perf gain without caching?

@i386
Copy link
Contributor Author

i386 commented Jan 5, 2017

@vivek most of the gains are made when Blue Ocean is using stapler's export package as each @exported method gets called with reflection. For Blue Ocean, there is a substantial amount of Method.invoke's occurring where the few milliseconds start to add up compared to using invokedynamic. A good analysis is http://andrewtill.blogspot.com.au/2011/08/using-method-handles.html

@vivek
Copy link
Contributor

vivek commented Jan 5, 2017

@i386 Thanks, tested that code locally, indeed MethodHandle speeds things up compared to reflection for large number of iterations.

Your changes LGTM 🐝

@i386
Copy link
Contributor Author

i386 commented Jan 5, 2017

@vivek did some testing here for 20 mins - it seems the more invocations we make the more the JVM can optimise them.

@i386
Copy link
Contributor Author

i386 commented Jan 5, 2017

Test failure is unrelated and intermittent

@kohsuke
Copy link
Member

kohsuke commented Jan 9, 2017

InstanceFunction should resolve a method to a handle in the constructor and keep the handle to avoid runtime lookup.

With that change, I don't think caching of MethodHandle is necessary, which reduces a complexity and eliminates an arbitrary configuration option (aka cache expiration period.)

I'm happy to make relevant changes and merge. I think it's also fine at this point to require Java7, and hopefully that'll drive some additional source code changes.

@i386
Copy link
Contributor Author

i386 commented Jan 9, 2017

@kohsuke ok that sounds great to me! Appreciate you reviewing these changes 👌

@kohsuke kohsuke merged commit 298b733 into jenkinsci:master Jan 14, 2017
kohsuke added a commit that referenced this pull request Jan 14, 2017
kohsuke referenced this pull request Jan 16, 2017
…c method,

as in the case with Klass.getFunctions() on a non-public class
@jglick
Copy link
Member

jglick commented Jan 19, 2017

I'm happy to make relevant changes and merge.

The standard procedure is to either request that the original filer do those changes, or to create a new PR subsuming the original one and adding further commits. In either case a fresh round of reviews is required.

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.

4 participants