在C#中优化多个调度通知算法?
作者:互联网
对不起标题,我想不出更好的方式来描述问题.基本上,我正在尝试在游戏中实现碰撞系统.我希望能够注册一个“冲突处理程序”,以处理可以转换为特定类型的两个对象(以任意顺序给出)的任何冲突.因此,如果注册了Player:Ship:Entity和Laser:Particle:Entity,并且注册了(Ship,Particle)和(Laser,Entity)的处理程序,而不是(Laser,Player)发生冲突,则应使用参数将两个处理程序通知按照正确的顺序,(激光,激光)的碰撞应仅通知第二个处理程序.
一个代码片段说了一千个单词,所以这就是我现在正在做的(天真的方法):
public IObservable<Collision<T1, T2>> onCollisionsOf<T1, T2>()
where T1 : Entity
where T2 : Entity
{
Type t1 = typeof(T1);
Type t2 = typeof(T2);
Subject<Collision<T1, T2>> obs = new Subject<Collision<T1, T2>>();
_onCollisionInternal += delegate(Entity obj1, Entity obj2)
{
if (t1.IsAssignableFrom(obj1.GetType()) && t2.IsAssignableFrom(obj2.GetType()))
obs.OnNext(new Collision<T1, T2>((T1) obj1, (T2) obj2));
else if (t1.IsAssignableFrom(obj2.GetType()) && t2.IsAssignableFrom(obj1.GetType()))
obs.OnNext(new Collision<T1, T2>((T1) obj2, (T2) obj1));
};
return obs;
}
但是,此方法相当慢(可测量;实施此方法后,我损失了约2 FPS),因此我正在寻找一种方法来减少此操作的几个周期/分配.
我想到了一种方法(例如,花了一个小时来实施,然后把脑袋撞成这样的白痴),该方法根据哈希码将类型按顺序排列,然后将其放入字典中,每个条目都是该类型对的处理程序的链接列表,带有布尔值,指示处理程序是否希望颠倒参数的顺序.不幸的是,这不适用于派生类型,因为如果派生类型被传入,它将不会通知基本类型的订阅者.没有人能想到一种比检查每个类型对(两次)是否匹配更好的方法吗?
谢谢,
罗伯特
解决方法:
所有的思考都不会很快.注意反射在每次碰撞中是如何发生的.那就是问题所在.
一些想法.
第一思想:访客模式.
用OO语言实现合理快速的双虚拟调度的标准方法是通过构建访客模式的实现.
您能否实现访客模式,从而使访客中的每个接受者都维护“在这种情况下要做的事情”的列表?然后,您的加法器方法包括确定编写新的“要做的事情”的正确位置,然后将委托添加到该事情中.发生冲突时,您可以启动访客进行双重调度,找到要做的事情的委托,然后调用它.
您是否需要双发以外的其他服务?高效的多虚拟调度是可行的,但并非一帆风顺.
思想二:动态调度
C#4具有动态调度.它的工作方式是我们在第一次遇到呼叫站点时使用反射来分析呼叫站点.然后,我们动态生成新的新IL来执行调用,并缓存该IL.在第二个调用中,我们对参数进行反思,以查看它们是否与以前完全相同.如果是这样,我们将重新使用现有的IL并对其进行调用.如果没有,我们将再次进行分析.如果参数通常只有几种类型,则高速缓存将很快开始只是命中而没有遗漏,并且考虑到所有因素,性能实际上是相当不错的.当然比每次反射都要快.我们每次所做的唯一反映就是对参数的运行时类型的分析.
思想三:实施自己的动态调度
DLR的工作没有什么神奇的.它只做一次分析,吐出一些IL并缓存结果.我怀疑您的痛苦正在发生,因为您每次都要重新进行分析.
标签:multiple-dispatch,events,c,net 来源: https://codeday.me/bug/20191106/2001078.html