在 Java 中使用 instanceof 的性能影响
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/103564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The performance impact of using instanceof in Java
提问by Josh
I am working on an application and one design approach involves extremely heavy use of the instanceof
operator. While I know that OO design generally tries to avoid using instanceof
, that is a different story and this question is purely related to performance. I was wondering if there is any performance impact? Is is just as fast as ==
?
我正在开发一个应用程序,一种设计方法涉及大量使用instanceof
运算符。虽然我知道 OO 设计通常试图避免使用instanceof
,但这是另一回事,这个问题纯粹与性能有关。我想知道是否有任何性能影响?是一样快==
吗?
For example, I have a base class with 10 subclasses. In a single function that takes the base class, I do checks for if the class is an instance of the subclass and carry out some routine.
例如,我有一个包含 10 个子类的基类。在采用基类的单个函数中,我会检查该类是否是子类的实例并执行一些例程。
One of the other ways I thought of solving it was to use a "type id" integer primitive instead, and use a bitmask to represent categories of the subclasses, and then just do a bit mask comparison of the subclasses "type id" to a constant mask representing the category.
我想解决的其他方法之一是使用“type id”整数原语,并使用位掩码来表示子类的类别,然后将子类“type id”与一个位掩码进行比较代表类别的常量掩码。
Is instanceof
somehow optimized by the JVM to be faster than that? I want to stick to Java but the performance of the app is critical. It would be cool if someone that has been down this road before could offer some advice. Am I nitpicking too much or focusing on the wrong thing to optimize?
被instanceof
莫名其妙地由JVM优化得比较快?我想坚持使用 Java,但应用程序的性能至关重要。如果以前走过这条路的人可以提供一些建议,那就太酷了。我是吹毛求疵还是专注于错误的优化?
采纳答案by Steve
Modern JVM/JIC compilers have removed the performance hit of most of the traditionally "slow" operations, including instanceof, exception handling, reflection, etc.
现代 JVM/JIC 编译器消除了大多数传统“慢”操作的性能损失,包括 instanceof、异常处理、反射等。
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.
正如唐纳德·克努斯 (Donald Knuth) 所写,“我们应该忘记 97% 的小效率:过早的优化是万恶之源。” instanceof 的性能可能不会成为问题,所以不要浪费时间想出奇特的变通方法,直到您确定这就是问题所在。
回答by Paul Tomblin
Generally the reason why the "instanceof" operator is frowned upon in a case like that (where the instanceof is checking for subclasses of this base class) is because what you should be doing is moving the operations into a method and overridding it for the appropriate subclasses. For instance, if you have:
通常,在这种情况下(其中 instanceof 正在检查此基类的子类)“instanceof”运算符不受欢迎的原因是因为您应该做的是将操作移到一个方法中并为适当的方法覆盖它子类。例如,如果您有:
if (o instanceof Class1)
doThis();
else if (o instanceof Class2)
doThat();
//...
You can replace that with
你可以用
o.doEverything();
and then have the implementation of "doEverything()" in Class1 call "doThis()", and in Class2 call "doThat()", and so on.
然后在 Class1 中实现“doEverything()”调用“doThis()”,在 Class2 中调用“doThat()”,依此类推。
回答by Outlaw Programmer
'instanceof' is actually an operator, like + or -, and I believe that it has its own JVM bytecode instruction. It should be plenty fast.
'instanceof'实际上是一个运算符,就像+或-一样,我相信它有自己的JVM字节码指令。它应该足够快。
I should not that if you have a switch where you are testing if an object is an instance of some subsclass, then your design might need to be reworked. Consider pushing the subclass-specific behavior down into the subclasses themselves.
我不应该说,如果您有一个开关来测试对象是否是某个子类的实例,那么您的设计可能需要重新设计。考虑将特定于子类的行为向下推入子类本身。
回答by Apocalisp
Instanceof is very fast. It boils down to a bytecode that is used for class reference comparison. Try a few million instanceofs in a loop and see for yourself.
Instanceof 非常快。它归结为用于类引用比较的字节码。在循环中尝试几百万个 instanceof 并亲眼看看。
回答by Karl
You should measure/profile if it's really a performance issue in your project. If it is I'd recommend a redesign - if possible. I'm pretty sure you can't beat the platform's native implementation (written in C). You should also consider the multiple inheritance in this case.
如果它确实是您项目中的性能问题,您应该测量/分析。如果是的话,我建议重新设计——如果可能的话。我很确定您无法击败平台的本机实现(用 C 编写)。在这种情况下,您还应该考虑多重继承。
You should tell more about the problem, maybe you could use an associative store, e.g. a Map<Class, Object> if you are only interested in the concrete types.
您应该更多地了解这个问题,如果您只对具体类型感兴趣,也许您可以使用关联存储,例如 Map<Class, Object>。
回答by Olaf Kock
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.
在考虑优化不需要优化的东西之前:以最易读的方式编写算法并运行它。运行它,直到 jit-compiler 有机会优化它本身。如果您对这段代码有问题,请使用分析器来告诉您从哪里获得最大收益并对其进行优化。
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.
并且本着这个答案的真正精神(我完全相信):一旦 jit 编译器有机会对其进行优化,我绝对不知道 instanceof 和 == 之间的关系。
I forgot: Never measure the first run.
我忘记了:永远不要测量第一次运行。
回答by tloach
You're focusing on the wrong thing. The difference between instanceof and any other method for checking the same thing would probably not even be measurable. If performance is critical then Java is probably the wrong language. The major reason being that you can't control when the VM decides it wants to go collect garbage, which can take the CPU to 100% for several seconds in a large program (MagicDraw 10 was great for that). Unless you are in control of every computer this program will run on you can't guarantee which version of JVM it will be on, and many of the older ones had major speed issues. If it's a small app you may be ok with Java, but if you are constantly reading and discarding data then you willnotice when the GC kicks in.
你专注于错误的事情。instanceof 与用于检查同一事物的任何其他方法之间的差异甚至可能无法衡量。如果性能至关重要,那么 Java 可能是错误的语言。主要原因是您无法控制 VM 决定何时开始收集垃圾,这可能会使大型程序中的 CPU 在几秒钟内达到 100%(MagicDraw 10 非常适合)。除非您控制着该程序将在其上运行的每一台计算机,否则您无法保证它将在哪个 JVM 版本上运行,而且许多较旧的计算机都存在严重的速度问题。如果它是一个小型应用程序,您可能会使用 Java,但如果您不断读取和丢弃数据,那么您会注意到 GC 何时启动。
回答by Mecki
It's hard to say how a certain JVM implements instance of, but in most cases, Objects are comparable to structs and classes are as well and every object struct has a pointer to the the class struct it is an instance of. So actually instanceof for
很难说某个 JVM 是如何实现实例的,但在大多数情况下,对象与结构相当,类也是如此,每个对象结构都有一个指向它是实例的类结构的指针。所以实际上 instanceof for
if (o instanceof java.lang.String)
might be as fast as the following C code
可能和下面的 C 代码一样快
if (objectStruct->iAmInstanceOf == &java_lang_String_class)
assuming a JIT compiler is in place and does a decent job.
假设 JIT 编译器到位并且做得不错。
Considering that this is only accessing a pointer, getting a pointer at a certain offset the pointer points to and comparing this to another pointer (which is basically the same as testing to 32 bit numbers being equal), I'd say the operation can actually be very fast.
考虑到这只是访问一个指针,在指针指向的某个偏移量处获取一个指针并将其与另一个指针进行比较(这与测试 32 位数字相等)基本相同,我会说该操作实际上可以非常快。
It doesn't have to, though, it depends a lot on the JVM. However, if this would turn out to be the bottleneck operation in your code, I'd consider the JVM implementation rather poor. Even one that has no JIT compiler and only interprets code should be able to make an instanceof test in virtually no time.
但是,它不是必须的,它在很大程度上取决于 JVM。但是,如果这会成为您代码中的瓶颈操作,我会认为 JVM 实现相当糟糕。即使是没有 JIT 编译器并且只解释代码的人也应该能够在几乎任何时间进行 instanceof 测试。
回答by Demian Krige
InstanceOfis a warning of poor Object Oriented design.
InstanceOf是对糟糕的面向对象设计的警告。
Current JVMs do mean the instanceOfis not much of a performance worry in itself. If you are finding yourself using it a lot, especially for core functionality, it is probably time to look at the design. The performance (and simplicity/maintainability) gains of refactoring to a better design will greatly outweigh any actual processor cycles spent on the actual instanceOfcall.
当前的 JVM 确实意味着instanceOf本身并没有太大的性能问题。如果您发现自己经常使用它,尤其是对于核心功能,那么可能是时候看看设计了。重构为更好的设计所带来的性能(和简单性/可维护性)收益将大大超过花费在实际instanceOf调用上的任何实际处理器周期。
To give a very small simplistic programming example.
给出一个非常小的简单编程示例。
if (SomeObject instanceOf Integer) {
[do something]
}
if (SomeObject instanceOf Double) {
[do something different]
}
Is a poor architecture a better choice would have been to have SomeObject be the parent class of two child classes where each child class overrides a method (doSomething) so the code would look as such:
如果架构很差,更好的选择是让 SomeObject 成为两个子类的父类,其中每个子类覆盖一个方法 (doSomething),因此代码如下所示:
Someobject.doSomething();
回答by Horcrux7
In modern Java version the instanceof operator is faster as a simple method call. This means:
在现代 Java 版本中,instanceof 运算符作为简单的方法调用速度更快。这意味着:
if(a instanceof AnyObject){
}
is faster as:
更快,因为:
if(a.getType() == XYZ){
}
Another thing is if you need to cascade many instanceof. Then a switch that only call once getType() is faster.
另一件事是,如果您需要级联许多 instanceof。然后只调用一次 getType() 的开关更快。