一尘不染

在Java中使用instanceof的性能影响

java

我正在开发一个应用程序,一种设计方法涉及大量使用instanceof操作员。虽然我知道OO设计通常会尝试避免使用instanceof,但这是另一回事了,这个问题与性能完全相关。我想知道是否会对性能产生影响?是一样快==吗?

例如,我有一个包含10个子类的基类。在采用基类的单个函数中,我检查该类是否是子类的实例并执行一些例程。

我想解决的另一种方法是改用“类型ID”整数基元,并使用位掩码表示子类的类别,然后将子类“类型ID”与位掩码进行位掩码比较。代表类别的常量掩码。

instanceof JVM 是否以某种方式对其进行了优化,使其速度更快?我想坚持使用Java,但应用程序的性能至关重要。如果以前曾走过这条路的人可以提供一些建议,那将很酷。我是否挑剔或专注于错误的东西进行优化?


阅读 3324

收藏
2020-03-07

共2个答案

一尘不染

现代的JVM / JIC编译器已消除了大多数传统的“慢速”操作对性能的影响,这些操作包括instanceof,异常处理,反射等。

正如Donald Knuth所说:“我们应该忘记效率低下的问题,大约有97%的时间是这样:过早的优化是万恶之源。” instanceof的性能可能不会成为问题,因此在确定这是问题之前,请不要浪费时间来寻求新的解决方法。

2020-03-07
一尘不染

方法

我编写了一个基准程序来评估不同的实现:

  1. instanceof 实施(作为参考)
  2. 通过抽象类和@Override测试方法定位的对象
  3. 使用自己的类型实现
  4. getClass() == _.class 实作

我使用jmh进行了100次预热调用,正在测量的1000次迭代以及10次fork来运行基准测试。因此,每个选项的测量结果均为1万次,这需要12:18:57才能在具有macOS 10.12.4和Java 1.8的MacBook Pro上运行整个基准测试。基准衡量每个选项的平均时间。有关更多详细信息,请参见我在GitHub上的实现。

为了完整起见:该答案有一个较早的版本和我的基准。

结果

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

instanceof尽管getClass()非常接近,但在Java 1.8中是最快的方法。

2020-03-07