XNA/C# : Entity Factories and typeof(T) performance

标签 xna c#

在我们的游戏(针对移动设备)中,我们有几种不同的实体类型,我正在编写一个工厂/存储库来处理新实体的实例化。每个具体实体类型都有自己的工厂实现,这些工厂由 EntityRepository 管理。

我想这样实现存储库:

Repository
{
 private Dictionary <System.Type, IEntityFactory<IEntity>> factoryDict;

 public T CreateEntity<T> (params) where T : IEntity
 {
      return factoryDict[typeof(T)].CreateEntity() as T;
 }
}

使用示例

var enemy = repo.CreateEntity<Enemy>();

但我关心的是性能,特别是与上面的 typeof(T) 操作有关。据我了解,编译器无法确定 T 的类型,必须在运行时通过反射来确定,这是正确的吗?一种选择是:

Repository
{
 private Dictionary <System.Type, IEntityFactory> factoryDict;

 public IEntity CreateEntity (System.Type type, params)
 {
      return factoryDict[type].CreateEntity();
 }
}

将用作

var enemy = (Enemy)repo.CreateEntity(typeof(Enemy), params);

在这种情况下,每当调用 typeof() 时,类型就在手边并且可以由编译器确定(对吗?)并且性能应该更好。会有显着差异吗?还有其他考虑吗?我知道我也可以在存储库中使用诸如 CreateEnemy 之类的方法(我们只有少数实体类型),这样速度会更快,但我更愿意让存储库尽可能保持实体不感知。

编辑:

我知道这很可能不是瓶颈,我担心的是,当有一种含糖量稍低的替代品可用时,花时间思考是一种浪费。我认为这是一个有趣的问题 :)

我做了一些基准测试,事实证明这很有趣(而且似乎证实了我最初的怀疑)。

使用我在 http://blogs.msdn.com/b/vancem/archive/2006/09/21/765648.aspx (多次运行测试方法并显示平均时间等指标)我进行了基本测试,测试:

private static T GenFunc<T>() where T : class 
    {

        return dict[typeof(T)] as T;
    }

反对

    private static Object ParamFunc(System.Type type)
    {
        var d = dict[type];
        return d;
    }

称为

str = GenFunc<string>();

对比

str = (String)ParamFunc(typeof(String));

分别。 Paramfunc 显示出显着的性能改进(平均执行时间是 GenFunc 的 60-70%),但测试非常初级,我可能遗漏了一些东西。特别是如何在通用函数中执行转换。

有趣的是,与每次使用 typeof() 相比,通过“缓存”变量中的类型并将其传递给 ParamFunc 获得的性能几乎没有(可以忽略不计)。

最佳答案

C# 中的泛型不使用也不需要反射。

内部类型作为 RuntimeTypeHandle 传递值。和 typeof运算符映射到 Type.GetTypeFromHandle (MSDN)。如果不查看 Rotor 或 Mono 进行检查,我会期望 GetTypeFromHandle为 O(1) 并且非常快(例如:数组查找)。

因此,在一般情况下(<T>),您实际上传递的是 RuntimeTypeHandle。进入你的方法并调用GetTypeFromHandle 您的方法中。在您的非通用案例中,您正在调用 GetTypeFromHandle首先然后传递结果 Type进入你的方法。性能应该几乎相同 - 并且大大超过其他因素,例如您分配内存的任何地方(例如:如果您使用 params 关键字)。

但无论如何它都是一个工厂方法。它肯定不会每秒被调用超过几次吗?它甚至值得优化吗?

关于XNA/C# : Entity Factories and typeof(T) performance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6779189/

相关文章:

c# - 贝塞尔曲面中的自动内部边缘

c# - 理解 Protobuf-net 属性的序列化和反序列化

c# - 如何使用用户 ID(对象 ID)从 Azure Active Directory 获取用户名

c# - 在游戏中制作大量咒语时遇到困难

c# - 加载和保存颜色值

c# - ObjectIDGenerator 实现

c# - msbuild/csproj 执行任务问题

c# - 列表中的碰撞检测

c# - 如何在 MediaPlayer 中播放来自 SpeechSynthesizer 的 wav 文件

c# - 如何将位图更改为另一种随机颜色?