• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Who called?

 
Koen Aerts
Ranch Hand
Posts: 344
Java Linux Oracle
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a method called "whoCalled". It returns the classname, methodname and line number of the method that called the original method. For instance say method A calls method B. If method B executes the whoCalled method, it will get the class/method name of method A.

Below is an example:


The output of above program is:

Basically in order to determine the calling method, I take the StackTrace (array of StackTraceElements) from a new Throwable instance, and return the 3rd item in that array (first item would the the whoCalled method itself, 2nd item the method that called it, etc.).

Are there other, perhaps more efficient or cleaner ways to achieve the same result, or is this it?
 
Jesper de Jong
Java Cowboy
Saloon Keeper
Pie
Posts: 15150
31
Android IntelliJ IDE Java Scala Spring
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As far as I know there isn't a much better / cleaner / more efficient way to do this.

I hope you're only using this for diagnostics (debug logging, for example). Your program will quickly become an entangled ball of spaghetti if the behaviour of methods changes depending on who's calling them. (You're adding nasty dependencies which will make the program very hard to understand).
 
Joanne Neal
Rancher
Pie
Posts: 3742
16
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's no need to create the Throwable instance. The Thread class has a method for giving you a stack trace.
 
Koen Aerts
Ranch Hand
Posts: 344
Java Linux Oracle
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tested the 2 different ways by timing "new Throwable()" vs "Thread.currentThread()" statements. It seems calling "new Throwable()" performs faster than "Thread.currentThread()" calls:

The result:

Not sure why that would be the case?
 
Paul Clapham
Sheriff
Pie
Posts: 20203
26
MySQL Database
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Or to convert that to the cost of a single call:



Or to put it another way, you're saving 0.8 microseconds by creating a new Throwable object. That doesn't seem like a savings I would be actively seeking, since presumably in real life you wouldn't be doing this process millions of times anyway. (Right?) However you haven't included the cost of having that Throwable object garbage-collected, so your savings are less than 0.8 microseconds per call and possibly even negative.
 
Joanne Neal
Rancher
Pie
Posts: 3742
16
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:Or to convert that to the cost of a single call:



Or to put it another way, you're saving 0.8 microseconds by creating a new Throwable object. That doesn't seem like a savings I would be actively seeking, since presumably in real life you wouldn't be doing this process millions of times anyway. (Right?) However you haven't included the cost of having that Throwable object garbage-collected, so your savings are less than 0.8 microseconds per call and possibly even negative.

Except that the Thread method does this

which means they are doing the same thing except the Thread method checks if the thread it's being called on is the current thread which I assume is what causes it to be slighly slower
 
Koen Aerts
Ranch Hand
Posts: 344
Java Linux Oracle
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The differences are probably negligible enough to be ignored. I just like to understand why things behave the way they do. For instance I had found that the String compareTo method is slighty faster than the equals method, however the equalsIgnoreCase method is significantly slower than equals.
 
Jesper de Jong
Java Cowboy
Saloon Keeper
Pie
Posts: 15150
31
Android IntelliJ IDE Java Scala Spring
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Koen Aerts wrote:The differences are probably negligible enough to be ignored. I just like to understand why things behave the way they do. For instance I had found that the String compareTo method is slighty faster than the equals method, however the equalsIgnoreCase method is significantly slower than equals.

Micro-benchmarking is very difficult to do correctly on the JVM.

The JIT (Just In Time) compiler, that compiles Java bytecode to native machine code at runtime, contains many very sophisticated optimizations. It contains complicated logic to determine when to compile what parts of the code to native machine code, does inlining and a whole list of other optimizations, and can even in some special cases de-optimize code and then recompile it again to machine code.

Simply calling a method N times and measuring how long it takes often doesn't give you a timing number that's accurate to the last digit. It depends heavily on what decisions the JIT makes and can be different on different machines, at different times or across different JVM versions.

If you know what the methods of the String class do exactly, you could lookup the source code of class String; you'll find the source code in the file src.zip in your JDK installation directory.
 
Campbell Ritchie
Sheriff
Pie
Posts: 47293
52
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You ought to use the nanoseconds method of the System class. And you will find that performance varies considerably on repeated runs.
 
Winston Gutkowski
Bartender
Pie
Posts: 9490
50
Eclipse IDE Hibernate Ubuntu
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:You ought to use the nanoseconds method of the System class. And you will find that performance varies considerably on repeated runs.

Except that System.nanoTime() takes about 5 times as long to run as System.currentTimeMillis() (at least on my machine).

Good old Heisenberg

Winston
 
Campbell Ritchie
Sheriff
Pie
Posts: 47293
52
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Earlier, I wrote: . . . you will find that performance varies considerably on repeated runs.
See, told you so.
 
Koen Aerts
Ranch Hand
Posts: 344
Java Linux Oracle
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jesper de Jong wrote:
Koen Aerts wrote:The differences are probably negligible enough to be ignored. I just like to understand why things behave the way they do. For instance I had found that the String compareTo method is slighty faster than the equals method, however the equalsIgnoreCase method is significantly slower than equals.

Micro-benchmarking is very difficult to do correctly on the JVM.

That's true. And I did find that consecutive runs give slightly different results each time; however I do think in some cases it provides useful information, especially in cases where the performance difference between similar functions is fairly large. For instance 1 billion iterations over the String equals() method took about 500ms, but about 27 seconds for the equalsIgnoreCase() method. But you're right; millisecond differences are probably in most cases negligible.
 
Randall Twede
Ranch Hand
Posts: 4353
2
Java
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
don't you listen to them Koen. you had it pretty right from the start
 
Paul Clapham
Sheriff
Pie
Posts: 20203
26
MySQL Database
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Following on from what Jesper mentioned about the JIT: if you're going to do a micro-benchmark where you time A and then time B, you should also do a similar micro-benchmark where you time B and then time A. That's because the JIT will wait for a while before it starts optimizing your code, so that earlier code can be less optimized.
 
I agree. Here's the link: http://aspose.com/file-tools
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic