当前位置:   article > 正文

由UnityEngine.Object该怎么判空引发的一些思考_unity 判空 性能 gameobject

unity 判空 性能 gameobject

1.测试数据分析

  先给出一组测试数据,分别用三种比较方式进行100万次UnityEngine.Object的判空。

比较方式耗时(毫秒)
obj == null43
obj is null4
System.Object.ReferenceEquals(obj, null)4

  一开始的时候用GameObject和继承MonoBehaviour组件拿到的测试结果不一样,GameObject用ReferenceEquals或者 is null比较速度只能提升一倍,后来发现是忘记缓存gameObject了(在MonoBehaviour脚本里直接写的gameobject是一个属性,虽然一般不会造成性能问题,但在测试时不加注意可能会得到错误的结论)。
  拿到这个数据后就可以开始猜测了,is null就是一个语法糖,通过上述数据可以猜测is null 会被翻译成ReferenceEquals。那么ReferenceEquals为什么会快这么多呢。

2.ReferenceEquals

  既然ReferenceEquals要快这么多,那就去看一下实现,不看不要紧,一看吓一跳,这不就是 == 么。一开始还怀疑是不是上面加的两个特性捣的鬼,查了一下排除了。

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[System.Runtime.Versioning.NonVersionable]
public static bool ReferenceEquals (Object objA, Object objB) {
    return objA == objB;
}
  • 1
  • 2
  • 3
  • 4
  • 5

  那么会不会是函数参数是system.object造成的呢,于是增加两种比较方式得到以下结果

比较方式耗时(毫秒)
obj == null43
obj is null4
(object)obj == (object)null4
SelfEquals(obj, null)9

SelfEquals实现如下

bool SelfEquals(object obj1, object obj2)
{
    return obj1 == obj2;
}
  • 1
  • 2
  • 3
  • 4

  到这里事情就有点意思了,到这时可以暂时理解为把UnityEngine.Object转成System.Object比较会快一些。自己写SelfEquals慢一点估计是因为多了一层函数调用。

  最后用ILSpy反编译一下unity生成的dll,发现直接使用==时,编译器翻译的最终c#代码是这样的

if ((Object)(object)obj == (Object)null){}
  • 1

  而其它几种都是这样的

if (obj == null){}
  • 1

  如果比较的不是UnityEngine.Object,而是继承自System.Object的类的话则最终翻译到的c#代码都是第二种情况。

3.总结

  unity有三大内存域,跨域的通信过渡会造成性能上的损失,由于UnityEngine.Object的数据是保存在本地域上,直接使用 == 时可能会引发本地域和托管域之间的桥梁通信过度,从而造成速度变慢。而把他们当作System.Object做比较时,应该是只在托管域中做了一次引用比较。

  • 本地域
  • 托管域
  • 外部dll
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/125610?site
推荐阅读
相关标签
  

闽ICP备14008679号