草庐IT

java - 传递接口(interface)和重新加载类之间的性能差异

coder 2024-03-06 原文

有一个 consensus使用接口(interface)比使用类更好。我当然同意:接受 ArrayList 而不是 List 的库方法将是一个废话。

还有一个共识是性能始终相同。这是我的 benchmark不同意。 接口(interface)和抽象类都有 1 到 4 个实现。当使用两个以上的实现时,性能开始出现差异。我正在寻找对此行为的解释(以及错误共识的起源)。

最佳答案

There's a consensus that using interfaces is better than using classes.

这太简单了。接口(interface)和抽象类各有优势。

您链接到的答案建议尽可能将变量声明为 java.util.List,而不是 java.util.ArrayList。正确的是,使用 List 可以让您以后更灵活地选择不同的实现类,因此当您不需要特定于 ArrayList 的方法(例如,.trimToCapacity())时,这是一件好事.但是,此建议一般与接口(interface)或类无关,如果 java.util.List 是抽象类,则同样如此。

There's also a consensus that the performance is always the same.

流行的建议是不要担心类和接口(interface)之间的性能差异,而应该根据良好的编程原则在它们之间进行选择。这是防止程序员为不重要的性能差异烦恼的好建议;然而,它有时会被误解为暗示没有 差异,这是不正确的。有一个的小区别:上课速度更快。

通过类的方法调用,有一个vtable在类中的固定偏移处,并且指向所需方法实现的指针位于该表中的已知偏移处,因此跳转到目标非常简单。然而,虽然一个类只能扩展一个父类(super class),但一个类可以实现任意数量的接口(interface),因此通过接口(interface)调用方法更加复杂。对于接口(interface)调用,它必须首先查找类的接口(interface)列表以找到所需的接口(interface),然后才能在该接口(interface)的表中查找方法实现。

When more than two implementations get used, the performance starts to diverge.

无论是使用类还是接口(interface),多态调用都会造成CPU上的pipeline flush,因为CPU无法提前看到跳转的目标,这样的代价很高。当调用站点在运行时已知为寡态(oligo 意思是“很少”)时,性能会急剧提高,因为好的 JVM 会专门处理这些情况。对于单态情况,JVM 可以直接跳转到单一目标方法,甚至内联它。对于双态情况,它实现 o.f(); 就像通过(无效语法):if (o.getClass() == A.class) A::f(o) else B::f(o);.

实际上,我不确定为什么双态情况在您的基准测试中似乎与单态情况一样快——CPU 的分支预测器不应该在随机数据上有一半的时间出错吗?也许还有其他微妙之处在起作用……

另见:

关于java - 传递接口(interface)和重新加载类之间的性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21608240/

有关java - 传递接口(interface)和重新加载类之间的性能差异的更多相关文章

  1. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  2. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  7. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  8. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  9. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  10. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

随机推荐