UnityEngine.Objectはどのように空を判断して引き起こしたいくつかの思考を判断します

4220 ワード

1.テストデータ分析


  まず1組のテストデータを提供し、それぞれ3種類の比較方式で100万回UnityEngine.Objectの判定が空です.
ひかくほうしき
時間(ミリ秒)
obj == null
43
obj is null
4
System.Object.ReferenceEquals(obj, null)
4
最初はGameObjectと継承MonoBehaviourコンポーネントで取得したテスト結果が異なり、GameObjectはReferenceEqualsまたはis nullで比較すると2倍しか速度が上がらず、後にgameObjectをキャッシュするのを忘れていることが判明した(MonoBehaviourスクリプトに直接書かれたgameobjectは属性であり、一般的には性能に問題はないが、テスト時に注意しないと誤った結論が得られる可能性がある).このデータを手に入れると推測が始まり、is nullは文法糖であり、上記のデータからis nullがReferenceEqualsに翻訳されると推測できる.ではReferenceEqualsはなぜこんなに速くなったのでしょうか.

2.ReferenceEquals


ReferenceEqualsがこんなに速くなる以上、実現を見に行きましょう.見なくても大丈夫です.見てびっくりします.これは==ではありませんか.最初は上に2つの特性を加えた鬼ではないかと疑っていたが、調べて排除した.
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[System.Runtime.Versioning.NonVersionable]
public static bool ReferenceEquals (Object objA, Object objB) {
    return objA == objB;
}

では、関数パラメータがsystemであるかどうか.objectによるものなので、2つの比較方式を増やして以下の結果を得た.
ひかくほうしき
時間(ミリ秒)
obj == null
43
obj is null
4
(object)obj == (object)null
4
SelfEquals(obj, null)
9
SelfEqualsは以下のように実現される
bool SelfEquals(object obj1, object obj2)
{
    return obj1 == obj2;
}

  ここまで来るとちょっと面白いですが、その時になったら一時的にUnityEngine.ObjectをSystemに変換する.Objectのほうが速いです.自分でSelfEqualsを書くのが遅い推定は、関数呼び出しが1つ増えたためです.
  最後にILSpyでunityで生成したdllを逆コンパイルしてみたところ、==を直接使用していることがわかりました.コンパイラが翻訳した最終c#コードはこうです
if ((Object)(object)obj == (Object)null){}

他のいくつかはこうです
if (obj == null){}

  比較がUnityEngineでない場合.ObjectではなくSystemから継承する.Objectのクラスでは最終的に翻訳されたc#コードが2番目のケースです.

3.まとめ


 unityには3つのメモリドメインがあり、ドメイン間の通信遷移はUnityEngineのため性能上の損失をもたらす.Objectのデータは,本地域に保存されており,==を直接使用すると,本地域と管理ドメイン間の橋渡し通信が過剰になり,速度が遅くなる可能性がある.彼らをシステムと見なしていますObjectを比較する場合、管理ドメインでのみ参照比較を行ったはずです.
  • 本地域
  • 管理ドメイン
  • 外部dll