在 Java 中使用 instanceof 的性能影响方法结果tl;博士

2022-08-31 04:52:46

我正在研究一个应用程序,一种设计方法涉及操作员的极重使用。虽然我知道OO设计通常试图避免使用,但这是一个不同的故事,这个问题纯粹与性能有关。我想知道是否有任何性能影响?是一样快吗?instanceofinstanceof==

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

我想解决这个问题的另一种方法是使用“type id”整数基元,并使用位掩码来表示子类的类别,然后只需将子类“type id”与表示类别的常量掩码进行比较。

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


答案 1

方法

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

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

我使用 jmh 运行基准测试,其中包含 100 个预热调用、1000 次测量迭代和 10 个分叉。因此,每个选项都测量了10 000次,这需要12:18:57才能在我的MacBook Pro上使用macOS 10.12.4和Java 1.8运行整个基准测试。基准测试衡量每个选项的平均时间。有关更多详细信息,请参阅我在 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;博士

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


答案 2

现代JVM / JIT编译器已经消除了大多数传统上“慢速”操作的性能影响,包括实例,异常处理,反射等。

正如唐纳德·高德纳(Donald Knuth)所写的那样,“我们应该忘记小效率,比如说大约97%的时间:过早的优化是万恶之源。instanceof的性能可能不会成为问题,所以不要浪费时间想出异国情调的解决方法,直到你确定这就是问题所在。


推荐