|
|
1
312
方法a benchmark program 要评估不同的实现,请执行以下操作:
我曾经 jmh my implementation on GitHub . 为了完整性:有一个 previous version of this answer and my benchmark . | 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;博士
在Java1.8中
|
|
2
288
现代JVM/JIT编译器已经消除了大多数传统的“慢”操作的性能影响,包括instanceof、异常处理、反射等。 正如Donald Knuth所写,“我们应该忘记小效率,比如说97%的时间:过早优化是万恶之源。”instanceof的性能可能不会成为问题,所以在确定问题所在之前,不要浪费时间想出奇异的解决方法。 |
|
|
3
75
我只是做了一个简单的测试,看看instanceOf performance与对一个只有一个字母的string对象的简单s.equals()调用相比有多好。 在10.000.000循环中,instanceOf给了我63-96毫秒,而字符串equals给了我106-230毫秒 我使用了JavaJVM6。
使用整数的.equals()而不是字符串的结果是相同的,只是当我使用==I时,它比instanceOf快20毫秒(在10.000.000循环中) |
|
4
20
我创造了一个 microbenchmark for four different methods of dispatch
|
|
5
19
回答你的最后一个问题:除非档案员告诉你,你在一个瞬间花费了荒谬的时间。F:是的,你在吹毛求疵。
根据这个答案的真实精神(我完全相信):一旦jit编译器有机会对instanceof和==进行优化,我绝对不知道它们之间的关系。 我忘了:永远不要测量第一次跑步。 |
|
|
6
15
我也有同样的问题,但因为我并没有找到类似于我的用例的“性能指标”,所以我编写了更多的示例代码。在我的硬件和Java 6&7,instanceof和switch on 10mln迭代之间的差异为
所以,instanceof的速度确实较慢,尤其是在大量if-else-if语句上,但在实际应用程序中,差异可以忽略不计。
|
|
|
7
12
显然,如果一节课
主要成本只是一个阅读!
|
|
|
8
6
instanceof在大多数现实世界的实现中可能比简单的equals要昂贵(也就是说,在那些真正需要instanceof的实现中,你不能仅仅通过覆盖一个常用方法来解决它,就像每本初学者教科书以及上面的Demian建议的那样)。 为什么呢?因为可能会发生的是,您有几个接口,它们提供一些功能(比如说,接口x、y和z),以及一些要操作的对象,这些对象可能(或不)实现其中一个接口。。。但不是直接的。比如说,我有: w延伸x A工具w B扩展A C扩展B,实现y
假设我正在处理一个D的实例,对象D。计算(d instanceof x)需要取d.getClass(),通过它实现的接口循环,以知道一个是否为==到x,如果不是,则对其所有祖先再次递归执行此操作。。。 在我们的例子中,如果你对这棵树进行广度优先的探索,假设y和z没有扩展任何东西,那么至少会得到8个比较结果。。。 真实世界的派生树的复杂性可能更高。在某些情况下,如果JIT能够在所有可能的情况下将d预先解析为扩展x的某个实例,那么JIT可以优化其中的大部分。然而,实际上,大多数情况下,您都将经历树遍历。
|
|
|
9
5
|
|
|
10
5
然而,使用大量instanceof表明存在设计问题。
|
|
|
11
5
我基于jmh java基准原型2.21编写了一个性能测试。JDK是openjdk,版本是1.8.0_212。测试机器是MacPro。 测试结果如下:
结果表明:getClass优于instanceOf,这与其他测试相反。然而,我不知道为什么。
|
|
|
12
4
通常,在这种情况下(instanceof正在检查此基类的子类),不赞成使用“instanceof”运算符的原因是,您应该将操作移动到方法中,并为适当的子类重写它。例如,如果您有:
你可以用
然后在类1中调用“doThis()”,在类2中调用“doThat()”,等等,实现“doEverything()”。 |
|
|
13
4
“instanceof”实际上是一个操作符,比如+或-,我相信它有自己的JVM字节码指令。它应该足够快。 我不应该说,如果您有一个开关,您正在测试一个对象是否是某个子类的实例,那么您的设计可能需要重新设计。考虑将子类特定行为向下推到子类本身。 |
|
14
4
可能与下面的C代码一样快
假设一个JIT编译器已经就位并且做得很好。
不过,这并不一定非得如此,这在很大程度上取决于JVM。但是,如果这将成为代码中的瓶颈操作,我会认为JVM实现相当差。即使是一个没有JIT编译器并且只解释代码的系统,也应该能够在几乎没有时间的情况下进行instanceof测试。 |
|
15
4
德米安和保罗提到了一个很好的观点; 然而 我非常喜欢小数据对象,这些小数据对象可以以多种方式使用。如果遵循覆盖(多态)方法,则对象只能“单向”使用。 这就是模式的由来。。。 您可以使用双重分派(就像在访问者模式中一样)来要求每个对象“调用”传递自己——这将解析对象的类型。 然而 (再次)您将需要一个可以“处理”所有可能的子类型的类。 我更喜欢使用策略模式,您可以为要处理的每个子类型注册策略。类似下面的内容。请注意,这只对精确的类型匹配有帮助,但其优点是它是可扩展的——第三方贡献者可以添加自己的类型和处理程序。(这对于OSGi这样的动态框架很好,可以添加新的bundle)
|
|
|
16
3
我会马上给你回电话。但一种完全避免问题(或缺少问题)的方法是为所有需要执行instanceof的子类创建父接口。该接口将是一组超级 需要对其执行instanceof check的子类中的方法。如果方法不适用于特定的子类,只需提供此方法的虚拟实现。如果我没有误解这个问题,我过去就是这样绕过这个问题的。 |
|
17
2
在现代Java版本中,instanceof操作符作为一个简单的方法调用速度更快。这意味着:
另一件事是,如果需要级联多个instanceof。那么只调用一次getType()的开关速度更快。 |
|
|
18
1
是对糟糕的面向对象设计的警告。 瞬间 这本身并不是什么性能问题。如果您发现自己经常使用它,特别是在核心功能方面,那么可能是时候看看设计了。重构到更好的设计所带来的性能(以及简单性/可维护性)收益将大大超过在实际设计上花费的任何实际处理器周期 瞬间 呼叫
是一个糟糕的体系结构更好的选择是让SomeObject成为两个子类的父类,其中每个子类重写一个方法(doSomething),因此代码看起来是这样的:
|
|
|
19
1
若速度是你们唯一的目标,那个么使用int常量来识别子类似乎只需要几毫秒的时间
糟糕的OO设计,但如果您的性能分析表明这就是您的瓶颈所在,那么可能。在我的代码中,分派代码占总执行时间的10%,这可能有助于总速度提高1%。 |
|
|
20
0
如果这真的是项目中的一个性能问题,您应该对其进行测量/分析。如果可能的话,我建议重新设计。我敢肯定,您无法打败平台的本机实现(用C编写)。在这种情况下,您还应该考虑多重继承。 您应该更多地了解这个问题,也许您可以使用关联存储,例如地图<类、对象>如果你只对混凝土类型感兴趣。 |
|
|
21
0
|
|
|
22
0
我也喜欢enum方法,但我会使用抽象基类强制子类实现
|
|
23
0
其中,对单个项调用head()将返回未更改的值。将代码替换为
|
|
|
24
-4
你把注意力放错地方了。instanceof和任何其他检查同一事物的方法之间的差异甚至可能无法测量。如果性能至关重要,那么Java可能是错误的语言。主要原因是,您无法控制VM何时决定要去收集垃圾,在一个大型程序中,这会使CPU在几秒钟内达到100%(MagicDraw 10非常适合)。除非你控制着这个程序将要运行的每台计算机,否则你无法保证它将运行在哪个版本的JVM上,而且许多旧版本的JVM都有严重的速度问题。如果它是一个小应用程序,您可能可以使用Java,但如果您不断地读取和丢弃数据,那么您就可以使用Java 请注意GC何时启动。 |
|
Sweepy Dodo · JSON lite的格式化 1 年前 |
|
|
giantjenga · 优化整数向量到二进制向量的转换 1 年前 |
|
Zegarek · Postgresql递归查询未提供预期结果 1 年前 |
|
|
Joe · 为什么这两个查询之间的性能存在如此大的差异? 1 年前 |
|
tic-toc-choc · 在`dplyr中高效使用列表进行过滤` 1 年前 |