CodingJar

Testing Unity Null Wrapper Speed

May 17th, 2014
354
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ----- File: NullScriptableObject.cs -----
  2.  
  3. using UnityEngine;
  4. using System.Collections;
  5.  
  6. /**
  7.  * This is a class made to mimic UnityEngine.Object's functionality when comparing objects.
  8.  * We wrap it so we can replace their comparison functionality and check the speed of different operations.
  9.  */
  10. public class NullScriptableObject : ScriptableObject
  11. {
  12.     public bool unityFakeDestroy;
  13.     public bool fastFakeDestroy;
  14.  
  15.     Object  nullObj;
  16.     Object  notNull;
  17.  
  18.     void OnEnable()
  19.     {
  20.         nullObj = new GameObject( "Null" );
  21.         Object.DestroyImmediate( nullObj, true );
  22.  
  23.         notNull = new GameObject( "NotNull" );
  24.     }
  25.  
  26.     void OnDisable()
  27.     {
  28.         DestroyImmediate( nullObj );
  29.         DestroyImmediate( notNull );
  30.     }
  31.  
  32.     /**
  33.      * We want to override Equals to mimic what UnityEngine.Object is doing
  34.      */
  35.     public override bool Equals (object o)
  36.     {
  37.         // This is the optimized destroy, which explicitly checks for null
  38.         if ( fastFakeDestroy )
  39.         {
  40.             if (o==null)
  41.                 return true;
  42.             else
  43.                 return nullObj.Equals(o);
  44.         }
  45.  
  46.         // This is using Unity's Equals() for when an object is destroyed.  It is slow.
  47.         if ( unityFakeDestroy )
  48.             return nullObj.Equals(o);
  49.  
  50.         // This is using Unity's Equals() for when an object is alive and well.
  51.         return notNull.Equals(o);
  52.     }
  53.  
  54.     /** Need to override this or you get a warning */
  55.     public override int GetHashCode ()  {   return base.GetHashCode (); }
  56.  
  57.     /**
  58.      * I'm using operator overloading with the BASE System.Object type so comparing against generically typed null objects works
  59.      */
  60.     public static bool operator ==( NullScriptableObject lhs, object rhs )
  61.     {
  62.         return object.ReferenceEquals(lhs, rhs) || (!object.ReferenceEquals(lhs, null) && lhs.Equals(rhs));
  63.     }
  64.  
  65.     /**
  66.      * Must define != when defining ==
  67.      */
  68.     public static bool operator !=( NullScriptableObject lhs, object rhs )
  69.     {
  70.         return !(lhs == rhs);
  71.     }
  72. }
  73.  
  74.  
  75. ----- New File - CompareSpeedTest.cs -----
  76.  
  77. using UnityEngine;
  78. using System.Collections;
  79.  
  80. /**
  81.  * This is a class which should live in your scene.  You right-click on it to use the Context-Menu item "Test Null Scriptable".
  82.  * This will benchmark your implementation of the equals operator against null in different situations.
  83.  */
  84. public class CompareSpeedTest : MonoBehaviour
  85. {
  86.     [SerializeField]    int     _numCompares = 500000;
  87.  
  88.     [ContextMenu("Test Null Scriptable")]
  89.     void TestNullScriptable()
  90.     {
  91.         object obj1 = new object();
  92.         bool equal = false;
  93.         float startTime = Time.realtimeSinceStartup;
  94.         for (int i = 0 ; i < _numCompares ; ++i)
  95.         {
  96.             equal = (obj1 == null);
  97.         }
  98.  
  99.         Debug.Log ( "C# Object Compare Is Null: " + equal + " Time Taken: " + (Time.realtimeSinceStartup - startTime) );
  100.  
  101.         //
  102.         // Start the Null ScriptableObject
  103.         //
  104.         var nullSO = ScriptableObject.CreateInstance<NullScriptableObject>();
  105.  
  106.         startTime = Time.realtimeSinceStartup;
  107.         for (int i = 0 ; i < _numCompares ; ++i)
  108.         {
  109.             equal = (null == nullSO); // This still calls operator==( NullScriptableObject, object )
  110.         }
  111.        
  112.         Debug.Log ( "Null Scriptable Object Is Null: " + equal + " Time Taken: " + (Time.realtimeSinceStartup - startTime) );
  113.         nullSO.unityFakeDestroy = true;
  114.  
  115.         startTime = Time.realtimeSinceStartup;
  116.         for (int i = 0 ; i < _numCompares ; ++i)
  117.         {
  118.             equal = nullSO.Equals(null);
  119.         }
  120.  
  121.         Debug.Log ( "Null Scriptable Object After Unity Destroy Is Null: " + equal + " Time Taken: " + (Time.realtimeSinceStartup - startTime) );
  122.         nullSO.fastFakeDestroy = true;
  123.  
  124.         startTime = Time.realtimeSinceStartup;
  125.         for (int i = 0 ; i < _numCompares ; ++i)
  126.         {
  127.             equal = nullSO.Equals(null);
  128.         }
  129.        
  130.         Debug.Log ( "Null Scriptable Object After Fast Destroy Is Null: " + equal + " Time Taken: " + (Time.realtimeSinceStartup - startTime) );
  131.  
  132.         object realNull = null;
  133.         Debug.Log ( "Test With Compare to RealNull: " + (nullSO == realNull) );
  134.  
  135.         DestroyImmediate( nullSO, true );
  136.     }
  137. }
RAW Paste Data