This was very cool, adding a profiler using MH

Rémi Forax forax at univ-mlv.fr
Fri Feb 17 02:05:33 PST 2012


On 02/17/2012 06:29 AM, John Rose wrote:
> On Feb 16, 2012, at 8:43 PM, Mark Roos wrote:
>
>> The key code is below and it shows the power of methodHandles is ways one may not expect.  And it
>> added almost nothing to the run time ( maybe a few %).  It inserts itself into each callsite target and
>> collect entry and exit data.
> Nice!
>
> As a bonus, your profile points are given a chance to modify the arguments and return value.
>
> If you don't want to pass the arguments and return value, you can use a void-returning combiner with foldArguments (instead of filterArguments).  The combiner will "see" the arguments and then "return nothing", allowing the invoker to continue as before.

Yes, in PHP.reboot I track the hotness of a method by calling a void 
returning method that will increment
a counter that is bound to the method.
My first version was using a code very similar to the code of Mark.
I have then switch to use a fold + a void-returning combiner when we 
decide to support that idiom.

>
> A different use of foldArguments would also let you pass both the original arguments and the return value to the profileExit routine, so it could see the whole call.  Something like this:
>
>     invoker = {spreader which takes standard RtObject[] array};
>     profileExit = {method of type (RtCallSite, RtObject, RtObject[]) =>  RtObject};
>     profileExit = insertArguments(profileExit, 0, thisCallSite);  // (RtObject, RtObject[]) =>  RtObject
>     invoker = foldArguments(profileExit, invoker);  // note that invoker serves as *combiner*
>
>     // add entry profiling last, so that profileExit will see (possibly) transformed arguments:
>     profileEntry = {method of type (RtCallSite, RtObject[]) =>  RtObject[]};
>     profileEntry = insertArguments(0, thisCallSite);  // (RtObject[]) =>  RtObject[]
>     invoker = filterArguments(invoker, profileEntry);
>
> You could also interpose on abnormal termination (exceptions), using guardWithCatch.

The try-finallly method handle combiner is one example of the cookbook:
http://code.google.com/p/jsr292-cookbook/source/browse/trunk/interceptors/src/jsr292/cookbook/interceptors/Interceptors.java#68 


>
> A relatively simple way to do take full control of traced calls is to delegate the actual calling to the profile routine, but this might (presently) hurt performance, since it will make all calls go through one hot point, profileWrapper:
>
>    invoker = {spreader which takes standard RtObject[] array};
>    profileWrapper = {method of type (RTCallSite, MethodHandle, RtObject[]) =>  RtObject};
>    // wrapped call will execute this: profileWrapper(thisCallSite, unwrappedInvoker, arg...)
>    invoker = insertArguments(profileWrapper, 0, thisCallSite, invoker);
>
> I'm glad you are enjoying the toolkit!
>
> -- John


cheers,
Rémi



More information about the mlvm-dev mailing list