The performance impact of using instanceof in Java
Approach
I wrote a benchmark program to evaluate different implementations:
-
instanceof
implementation (as reference) - object-orientated via an abstract class and
@Override
a test method - using an own type implementation
-
getClass() == _.class
implementation
I used jmh to run the benchmark with 100 warmup calls, 1000 iterations under measuring, and with 10 forks. So each option was measured with 10 000 times, which takes 12:18:57 to run the whole benchmark on my MacBook Pro with macOS 10.12.4 and Java 1.8. The benchmark measures the average time of each option. For more details see my implementation on GitHub.
For the sake of completeness: There is a previous version of this answer and my benchmark.
Results
| Operation | Runtime in nanoseconds per operation | Relative to instanceof | |------------|--------------------------------------|------------------------| | INSTANCEOF | 39,598 ± 0,022 ns/op | 100,00 % | | GETCLASS | 39,687 ± 0,021 ns/op | 100,22 % | | TYPE | 46,295 ± 0,026 ns/op | 116,91 % | | OO | 48,078 ± 0,026 ns/op | 121,42 % |
tl;dr
In Java 1.8 instanceof
is the fastest approach, although getClass()
is very close.
Modern JVM/JIT compilers have removed the performance hit of most of the traditionally "slow" operations, including instanceof, exception handling, reflection, etc.
As Donald Knuth wrote, "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." The performance of instanceof probably won't be an issue, so don't waste your time coming up with exotic workarounds until you're sure that's the problem.
I just made a simple test to see how instanceOf performance is comparing to a simple s.equals() call to a string object with only one letter.
in a 10.000.000 loop the instanceOf gave me 63-96ms, and the string equals gave me 106-230ms
I used java jvm 6.
So in my simple test is faster to do a instanceOf instead of a one character string comparison.
using Integer's .equals() instead of string's gave me the same result, only when I used the == i was faster than instanceOf by 20ms (in a 10.000.000 loop)
The items which will determine the performance impact are:
- The number of possible classes for which the instanceof operator could return true
- The distribution of your data - are most of the instanceof operations resolved in the first or second attempt? You'll want to put your most likely to return true operations first.
- The deployment environment. Running on a Sun Solaris VM is significantly different than Sun's Windows JVM. Solaris will run in 'server' mode by default, while Windows will run in client mode. The JIT optimizations on Solaris, will make all method access able the same.
I created a microbenchmark for four different methods of dispatch. The results from Solaris are as follows, with the smaller number being faster:
InstanceOf 3156
class== 2925
OO 3083
Id 3067
Answering your very last question: Unless a profiler tells you, that you spend ridiculous amounts of time in an instanceof: Yes, you're nitpicking.
Before wondering about optimizing something that never needed to be optimized: Write your algorithm in the most readable way and run it. Run it, until the jit-compiler gets a chance to optimize it itself. If you then have problems with this piece of code, use a profiler to tell you, where to gain the most and optimize this.
In times of highly optimizing compilers, your guesses about bottlenecks will be likely to be completely wrong.
And in true spirit of this answer (which I wholeheartly believe): I absolutely don't know how instanceof and == relate once the jit-compiler got a chance to optimize it.
I forgot: Never measure the first run.