2

For the profiler which I implement using JVMTI I would like to start measuring the execution time of all Java methods. The JVMTI offers the events:

  • MethodEntry
  • MethodExit

So this would be quite easy to implement, however I came across this note in the API:

Enabling method entry or exit events will significantly degrade performance on many platforms and is thus not advised for performance critical usage (such as profiling). Bytecode instrumentation should be used in these cases.

But my profiling agent works headless, which means the collected data is serialized and sent via socket to a server application displaying the results. How should I realize this using byte code instrumentation. I am kind of confused how to go on from here. Could someone explain to me, if I have to switch the strategy or how can I approach this problem?

Konrad Reiche
  • 27,743
  • 15
  • 106
  • 143
  • It sounds like you want to create your own profiler. I would suggest you look at how existing profiles work like VisualVM and YourKit work to see if they don't do what you need already. – Peter Lawrey May 11 '11 at 10:47
  • They do, I just want to do it myself. But VisualVM could be a hint, to see how they do it, but my educated guess is they use Java agent and not a native agent. – Konrad Reiche May 11 '11 at 10:57
  • VisualVM uses a Java agent which you can get the source for. YourKit use a native agent which you can't get source for. Recording the data is not as hard as getting the visualisation of the data right. I would look at how YourKit does its visualisation. – Peter Lawrey May 11 '11 at 10:58
  • The visualization is the next step, I mean I could use the named JVMTI events MethodEntry and MethodExit in order to see, how big the difference is without instrumentation, however, I still would like to do it the right way. So far I cannot see how I can instrument a class method to gather data and send these data to a socket, the same way I do it in native code right now. – Konrad Reiche May 11 '11 at 11:01
  • I think you are going to a lot of trouble for a solution which is likely to be not as good as a professional one, however... When you create an agent, you can define a `premain` which is passed an `Instrumentation` which gets all the byte code of every class which is loaded. It can also be used to re-load classes later. You can use a library like ObjectWeb ASM to change the byte code to insert to code for timers/counter for methods, fields etc (anything you like) and store this in a POJO data structure which you can send over a plain Socket. – Peter Lawrey May 11 '11 at 11:06
  • Thanks, I should mention this is for my bachelor thesis, so this task is academic and not as good as professional solutions offers a lot of space for evaluation. The ObjectWeb ASM framework is not new to me, the only think Is that I always thought this is for ByteCode instrumentation from Java only. – Konrad Reiche May 11 '11 at 11:09
  • It is, You can use it from a Java agent, or a native agent all the same. – Peter Lawrey May 11 '11 at 11:13

1 Answers1

1

I don't know about the Sun JVM but the IBM JVM goes into what we call FullSpeedDebug mode when you request the MethodEntry/Exit events.... FSD slows down execution quite a bit.

As you say you can use BCI as my profiler does but unless you are selective about which methods you instrument you will also see a slow down. For example my profiler inserts a if(profiling) callProfilerHook() on every entry and all of the possible exits in a method all object creates and some other areas as well.... These additional checks can slow down execution by over 50%...

As for how to BCI... well I wrote my own C library to do it... it's technically not hard (hint just delete the StackMapTable) but I may take you a while.. Alternatively you can use ASM et. al.

Finally... you callBackHook will add overhead and on small methods render the reported CPU/Clock time meaningless unless you perform some sophisticated overhead calculation... even if you do this your callback code affects the shape of the processor L1 caches and the Java code becomes less efficient because it has less room..

My profiler basically ignores the reported times as I visualize the execution in an interesting way... I'm looking to understand the flow of all of the code, in fact in most cases what code is running (most Java projects have no idea of the millions on lines of third-party code running in their app)

  • Hey there, thanks again for the advices you gave me in another question here on stackoverflow, it really got my project rolling. I really like your argumentation and I think this is a point which I will catch on. Since I would like to measure where the most time is spent and not how long a method exactly needs. So you could say, MethodEntry and MethodExit are still useable? By the way, my project can now be found on: https://github.com/platzhirsch/Profiling-Concurrency – Konrad Reiche May 11 '11 at 11:40