2012年5月1日星期二

一种代替dynamic_cast的模版RTTI实现

在arch框架中,存在这样一种场景:一个IO Channel上顺序注册了一组handler,分别处理不同类型的事件消息,则当某个事件消息到达时,需要依次判断handler是否能处理该类型的消息。(参考自Jboss-Netty的设计)。这类操作是在网络服务是进行,执行次数最多,因此需要考虑一个高效的实现。
最初的实现是模仿Netty中Java的实现,用dynamic_cast判断(Java中是InstanceOf判断),但用dynamic_cast总觉得不太优雅,性能可能也存在问题(参考附注)。
最近有些空闲时间,重新思考了下这个问题,用了另外一种方法代替dynamic_cast实现
1. 注册handler接口方法用模版方法代替,将该携带类型信息的handler注册到一个和该类型相关的模版类中,如红色框部分。当然,在handler析构时需要去注册    image
image
2. 和该类型相关的模版类用静态set保存注册信息;
image
3. 判断事件类型与handler相关联信息,则可调用该模版类的静态方法。时间复杂度为set的实现决定。这里用tr1::unordered_set保存指针,时间复杂度为O(1)。 从理论上应当比用dynamic_cast快的多。(测试发现新方案较dynamic_cast实现快60%以上)
附注:
1. Google的编程规范强烈建议不要在产品代码中使用dynamic_cast。
2. 据一份评测报告显示,一次dynamic_cast可能消耗数十微秒,这个评测待验证。数十微秒显然太慢了。

2 条评论:

  1. 在RegisterHandler里用dynamic_cast来判断,再放到不同的set中?
    原先看netty里用instanceof来判断也觉得奇怪,其实我觉得直接在Handler接口里加两个函数(虽然有点丑陋):
    isUpStreamHandler和isDownStreamHandler就可以了。

    回复删除
  2. 之前用dynamic_cast主要是用于判断消息T是否能被handler X处理,和netty中的用instanceof判断是一样的。后来改成模板实现。
    netty中把这一步交给每个handler判断,可能是设计为handler可能会处理多种类型消息(我以为并不好),也可能是因为Java中的泛型是非完全的,在netty框架中是无法判断的。

    回复删除