【问题标题】:Overhead of searching and calling a method with reflection使用反射搜索和调用方法的开销
【发布时间】:2009-04-27 13:49:33
【问题描述】:

我有一个类应该读取消息,从信封中提取其类型,然后调用必须处理消息的方法;每个消息类型都关联一个枚举成员。

有 30 多种消息类型。

发送消息的一种方法是只使用一个开关,但它真的很丑而且容易出错(我是否已经处理过这种情况?我是否已经处理过两次?)。

另一种方法是使用单个方法 process(data) 定义接口,并为实现该接口的每个消息类型创建一个类,使用映射注册这些类,并且在应该处理消息的代码中,只需调用 map.get(messageType).process(data);但是创建 30+ 个类真的很烦人。

另一种方法是使用反射:为每个消息类型定义一个函数,具有精确的签名和模式名称,如 processMessagetype;然后创建一个从 messagetype 到 Method 的映射(在 getDekkaredMethods() 上进行简单搜索),然后执行以下操作: map.get(messageType).invoke(this,data).

你应该使用什么方法?使用java的反射有什么开销?

【问题讨论】:

    标签: java reflection


    【解决方案1】:

    如果您正在寻找良好的性能,反射会产生很大的开销。如果您的例程(消息调度)将被一遍又一遍地使用,那么多态替代方案会更好。此外,IMO 最好从 OO 的角度来看,因为正如 Brian 在他的回答中所说,维护更容易且更便宜。

    您处理 30 多条消息的类很容易增长到 100 多条消息,然后您将拥有一个包含 100 多个方法的类,还要添加私有方法,代码重用将变得困难,您的类就变得一团糟。

    多态性和开关的反射开销是这样的:

    time spent on a switch case call: 1
    time spent on a polymorphism call: 1.1
    time spent on a reflection call: 1.9-2.0
    

    我不久前对这些人进行了基准测试,这些是我的结果,我现在没有代码,因为这些基准测试是在我以前的公司完成的,我无法再访问该代码了。

    【讨论】:

    • 太好了,这正是我要寻找的。非常感谢!
    【解决方案2】:

    您可以将 process 方法添加到枚举中。

    大开关到底有什么问题(每种情况都只是调用一个方法)?

    反射的主要代价是它会使代码变得糟糕。 ;)

    【讨论】:

      【解决方案3】:

      您没有说您的 process() 方法将要做什么,但如果调度方法调用的任何开销非常重要,我会感到惊讶。

      我会让语言和 OO 系统为您工作,并创建一个具有适当方法实现的接口/抽象基类。

      请记住,过早的优化是万恶之源 (Knuth)

      【讨论】:

        【解决方案4】:

        我猜,因为您在谈论“消息”和“信封”,您正在通过网络传递这些消息。这样做所花费的时间绝对会支配反射所花费的额外时间。我用过这样的反射,这不是一个糟糕的模型。

        【讨论】:

        • 是的,但我使用的是异步 I/O,因此单个线程应该处理来自可能庞大的连接集的消息,因此频率很高。
        • 异步 I/O 肯定会增加您可以处理的消息数量,但它不会提高处理 one 消息的性能。正如我所说,这可能取决于通过线路发送消息所花费的时间或“处理”消息的时间。反射不会产生任何影响。 :-)
        • 嗯,重点是,对于异步 I/O,写入和读取操作不会阻塞,所以我不应该在等式中考虑这些时间。如果这种推理有缺陷,请随时纠正我;)
        【解决方案5】:

        我认为您描述的第一个方法/算法(消息类型到类的映射)会随着时间的推移通过更新、维护等更容易管理。

        您描述的第二种模式基本上涉及一个包含大约 30 多个方法的类,对吗?随着时间的推移,这将是一件相当痛苦的事情。

        每种消息类型都需要真正独特的处理逻辑吗?通过创建处理消息的接口的实现,您可能会受益于类型层次结构,即可以处理解析某个消息系列的超类,然后您只需在该系列的消息不同的区域覆盖它。 ..

        【讨论】:

        • 关于各种方法的代码可重用性问题的要点。是的,每个函数的逻辑都不同,它们非常小(通常它们只是通知与消息关联的事件的某些类,仅此而已)。各种功能的小因素(2-3行代码)让我想到了反射;否则我肯定会选择接口解决方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-19
        • 2012-08-08
        相关资源
        最近更新 更多