コードを書いていてnullチェックをすることはかなり多い。
1個1個の処理は小さくても、何千個ものオブジェクトで毎フレームnullチェックしているようでは処理時間を無駄に使っている
どうすれば処理時間を軽減できるか検証した
結論
何も考えずif(target != null)を使え
検証方法
Unityバージョン 5.5.0f3
3つの手法で検証した
- if(target != null)
- if(object.ReferenceEquals(target , null) == false )
- try - catch
対象オブジェクトがnullでない場合
NullTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NullTest : MonoBehaviour
{
readonly int COUNT = 10000000;
public class TestClass
{
public TestClass(){}
public void Test (){}
};
TestClass _TestClass = new TestClass();
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown (KeyCode.A)) {
float startTime = 0f;
startTime = Time.realtimeSinceStartup;
for (int i = 0; i < COUNT; i++) {
_TestClass.Test (); //nullチェックなし
}
float lap0 = Time.realtimeSinceStartup - startTime;
startTime = Time.realtimeSinceStartup;
for (int i = 0; i < COUNT; i++) {
if (_TestClass != null) {
_TestClass.Test ();
}
}
float lap1 = Time.realtimeSinceStartup - startTime;
startTime = Time.realtimeSinceStartup;
for (int i = 0; i < COUNT; i++) {
if (object.ReferenceEquals(_TestClass,null)==false) {
_TestClass.Test ();
}
}
float lap2 = Time.realtimeSinceStartup - startTime;
startTime = Time.realtimeSinceStartup;
for (int i = 0; i < COUNT; i++) {
try{
_TestClass.Test();
}
catch(System.Exception e) {
}
}
float lap3 = Time.realtimeSinceStartup - startTime;
Debug.Log (lap0);
Debug.Log (lap1);
Debug.Log (lap2);
Debug.Log (lap3);
}
}
}
手法 | 実行時間[sec] |
---|---|
(参考) nullチェックなし | 0.1567643 |
if(target != null) | 0.163532 |
if(object.ReferenceEquals(target , null) == false ) | 0.2293189 |
try-catch | 0.1630554 |
try-catchがわずかに早い
対象オブジェクトがnullの場合
上記コードの_TestClassをnullにして検証
手法 | 実行時間 |
---|---|
if(target != null) | 0.07411861 |
if(object.ReferenceEquals(target , null) == false) | 0.1276345 |
try-catch | 遅すぎて実行不可 |
try-catchはnullだった場合にとても遅くなる
参考
object.ReferenceEqualsは癖がある模様
object.ReferenceEquals(someObject, null) の方が someObject == null より早い…が、盲目的に使うのは危険