Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

What is faster? (proper property using)

Discussion in 'Scripting' started by CunningLobster, Jan 27, 2022.

  1. CunningLobster

    CunningLobster

    Joined:
    Jun 25, 2020
    Posts:
    10
    Hello! What peace of code has better performance:
    1. Properties only:
    Code (CSharp):
    1.     public int Purple { get => PlayerPrefs.GetInt("Purple", 0); private set => PlayerPrefs.SetInt("Purple", value); }
    2.     public int Red { get => PlayerPrefs.GetInt("Red", 0); private set => PlayerPrefs.SetInt("Red", value); }
    3.     public int Blue { get => PlayerPrefs.GetInt("Blue", 0); private set => PlayerPrefs.SetInt("Blue", value); }
    4.     public int Green { get => PlayerPrefs.GetInt("Green", 0); private set => PlayerPrefs.SetInt("Green", value); }
    5.     public int Brown { get => PlayerPrefs.GetInt("Brown", 0); private set => PlayerPrefs.SetInt("Brown", value); }
    6.  
    7. //Some methods which use those properties
    2. Fields + properties + cache
    Code (CSharp):
    1.     private int purple;
    2.     private int red;
    3.     private int blue;
    4.     private int green;
    5.     private int brown;
    6.    
    7.     public int Purple { get => purple; private set => purple = value;  }
    8.     public int Red { get => red; private set => red = value; }
    9.     public int Blue { get => blue; private set => blue = value; }
    10.     public int Green { get => green; private set => green = value; }
    11.     public int Brown { get => brown; private set => brown = value; }
    12.  
    13.     private void Awake()
    14.     {
    15.         purple = PlayerPrefs.GetInt("Purple", 0);
    16.         red = PlayerPrefs.GetInt("Red", 0);
    17.         blue = PlayerPrefs.GetInt("Blue", 0);
    18.         green = PlayerPrefs.GetInt("Green", 0);
    19.         brown = PlayerPrefs.GetInt("Brown", 0);
    20.     }
    21. //Some methods which use fields
    It seems to me that second variant is faster, but how much faster?
    And I don't really understand if it's expensive or not using
    get => PlayerPrefs.GetInt()
    ?
    And is the
    get => PlayerPrefs.GetInt()
    is already cached value or it's better to cache it with a variable?
     
    Last edited: Jan 27, 2022
  2. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    Make 2 separate scripts. As shown in your examples.

    Make 2 additional scripts —-
    These scripts will execute every update and must be arranged in script execution order

    Execution order -
    1. TimeGrabScript - check time system (or start timer)
    2. PropertiesOnlyScript
    3. TimeCompareScript - check time system (or stop timegrabscript timer)

    tell you how fast that script is I suppose

    for the 4. AwakeVersion - check time on the first line, check time last line of awake. Should get a length of time of that script. Checking time ofc takes time depending where that time was pulled from.

    let us know the results


    You might want to add times to a list. And get the average. Or make a fifth script to completely stop update time and thus prevent execution order from repeating after 1 cycle. This stop time script will be last in the execution order
     
  3. CunningLobster

    CunningLobster

    Joined:
    Jun 25, 2020
    Posts:
    10
    I don't get it...
    In the first case I need to check time every update like this?
    Code (CSharp):
    1. public class TimeGrabber : MonoBehaviour
    2. {
    3.     void Update()
    4.     {
    5.         Debug.Log("Grabbed at: " + Time.realtimeSinceStartup);
    6.     }
    7. }
    8.  
    Code (CSharp):
    1. public class TimeStopper : MonoBehaviour
    2. {
    3.     private void Update()
    4.     {
    5.         Debug.Log("Stopped at: " + Time.realtimeSinceStartup);
    6.     }
    7. }
    8.  
    But in the second case only once like this?
    Code (CSharp):
    1.     private void Awake()
    2.     {
    3.         Debug.Log("Grabbed at: " + Time.realtimeSinceStartup);
    4.  
    5.         purple = PlayerPrefs.GetInt("Purple", 0);
    6.         red = PlayerPrefs.GetInt("Red", 0);
    7.         blue = PlayerPrefs.GetInt("Blue", 0);
    8.         green = PlayerPrefs.GetInt("Green", 0);
    9.         brown = PlayerPrefs.GetInt("Brown", 0);
    10.  
    11.         Debug.Log("Stopped at: " + Time.realtimeSinceStartup);
    12.     }
    13. }
    14.  
     
  4. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    Oh Real time since start up I didn’t expect you to use this I’m not sure. But the theory is you can get a reading via the execution order to find out how long it took the entire execution order to run from the first point of time logged to the last point of time logged at the end of the execution order. Times Subtracted from one another should give the time. It may be so small you are not getting any noticable difference. Real-time since start up I really am not to sure I would have used system time to get a reading in that can be converted to milliseconds.


    I guess problem with time since start up is that it’s including all unity stuff that occurs before the script execution order, another thing is that I don’t know what the priority of unities real time since start up is, but I know it’s going to be of less priority to system time.
     
    Last edited: Jan 27, 2022
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,533
    You just provided a partial script which literally does nothing. So JUST from your provided code we can immediately tell that your first example would have a better performance because you literally do nothing. You defined some properties which you never ever use anywhere. So the second example will perform worse since you read all the player prefs once.

    However it's quite obvious that's most likely not what you wanted to know. Though to give a proper answer, the question is how often you actually access those properties. Here's an example just to measure the time:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class PlayerPrefsSpeedTest : MonoBehaviour
    5. {
    6.     public int Purple { get => PlayerPrefs.GetInt("Purple", 0); private set => PlayerPrefs.SetInt("Purple", value); }
    7.     public int Red { get => PlayerPrefs.GetInt("Red", 0); private set => PlayerPrefs.SetInt("Red", value); }
    8.     public int Blue { get => PlayerPrefs.GetInt("Blue", 0); private set => PlayerPrefs.SetInt("Blue", value); }
    9.     public int Green { get => PlayerPrefs.GetInt("Green", 0); private set => PlayerPrefs.SetInt("Green", value); }
    10.     public int Brown { get => PlayerPrefs.GetInt("Brown", 0); private set => PlayerPrefs.SetInt("Brown", value); }
    11.  
    12.     private int purple;
    13.     private int red;
    14.     private int blue;
    15.     private int green;
    16.     private int brown;
    17.  
    18.     public int Purple1 { get => purple; private set => purple = value; }
    19.     public int Red1 { get => red; private set => red = value; }
    20.     public int Blue1 { get => blue; private set => blue = value; }
    21.     public int Green1 { get => green; private set => green = value; }
    22.     public int Brown1 { get => brown; private set => brown = value; }
    23.  
    24.     private void Awake()
    25.     {
    26.         purple = PlayerPrefs.GetInt("Purple", 0);
    27.         red = PlayerPrefs.GetInt("Red", 0);
    28.         blue = PlayerPrefs.GetInt("Blue", 0);
    29.         green = PlayerPrefs.GetInt("Green", 0);
    30.         brown = PlayerPrefs.GetInt("Brown", 0);
    31.     }
    32.  
    33.     private void OnDestroy()
    34.     {
    35.         PlayerPrefs.SetInt("Purple", purple);
    36.         PlayerPrefs.SetInt("Red", red);
    37.         PlayerPrefs.SetInt("Blue", blue);
    38.         PlayerPrefs.SetInt("Green", green);
    39.         PlayerPrefs.SetInt("Brown", brown);
    40.         PlayerPrefs.Save();
    41.     }
    42.  
    43.     void OnGUI()
    44.     {
    45.         if (GUILayout.Button("Start Test"))
    46.         {
    47.             int max = 1000000;
    48.             var sw = new System.Diagnostics.Stopwatch();
    49.             sw.Start();
    50.             Purple = Red = Blue = Green = Brown = 0;
    51.             for (int i = 0; i < max; i++)
    52.             {
    53.                 int v = Purple + Red - Blue + Green + Brown + 1;
    54.                 Purple = Red;
    55.                 Red = Blue;
    56.                 Blue = Green;
    57.                 Green = Brown;
    58.                 Brown = v;
    59.             }
    60.             var res1 = Brown;
    61.             sw.Stop();
    62.             var t1 = sw.ElapsedMilliseconds;
    63.             var ticks1 = sw.ElapsedTicks;
    64.  
    65.  
    66.             sw.Reset();
    67.             sw.Start();
    68.             Purple1 = Red1 = Blue1 = Green1 = Brown1 = 0;
    69.             for (int i = 0; i < max; i++)
    70.             {
    71.                 int v = Purple1 + Red1 - Blue1 + Green1 + Brown1 + 1;
    72.                 Purple1 = Red1;
    73.                 Red1 = Blue1;
    74.                 Blue1 = Green1;
    75.                 Green1 = Brown1;
    76.                 Brown1 = v;
    77.             }
    78.             var res2 = Brown1;
    79.             sw.Stop();
    80.             var t2 = sw.ElapsedMilliseconds;
    81.             var ticks2 = sw.ElapsedTicks;
    82.             Debug.Log("with properties: " + t1 + " ms\nticks: "+ticks1+"\nres: " + res1);
    83.             Debug.Log("with cache: " + t2 + " ms\nticks: " + ticks2 + "\nres: " + res2);
    84.         }
    85.     }
    86. }
    87.  

    The class contains both of your suggestions, though I added the "saving" as well in your cached example. Be warned: Running this test on my machine took about 2 minutes and 15 sec. In this test each iteration we read 9 times a property and we write to 5 properties. We do this a million times and measure the over all time for both cases. The results are:

    Code (CSharp):
    1.  
    2. with properties: 135426 ms
    3. ticks: 1354266693
    4. res: 990770170
    5.  
    6. with cache: 2 ms
    7. ticks: 26340
    8. res: 990770170
    9.  
    So the results should be quite obvious. One iteration with the direct access of the playerprefs took about 0.000135 seconds (or 0.135ms) while one iteration with the cached properties only took 0.00000000263 seconds (or 0.00000263ms or 2.63ns). The initial loading or saving at the end is pretty irrelevant since it's a one time event.

    However there's one major difference. The cached version only actually saves the playerprefs when the application is closed / stopped. When the game crashes, nothing would be saved. PlayerPrefs itself also does not immediately store the values either. To force a writing to disk one has to call PlayerPrefs.Save()

    So we're back to the start... where and how are those properties used and how often? That's the only thing that really matters. I did another seperate test to see the difference in writing and reading playerprefs. Reading seems to be a bit faster compared to writing. Though both are not that great. 5M read operations took about 32 seconds while 5M write operations took 59 seconds.
     
    CunningLobster likes this.
  6. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164

    Fascinating read bunny hoppins
     
  7. CunningLobster

    CunningLobster

    Joined:
    Jun 25, 2020
    Posts:
    10
    Thank you so much! You explained me everything I wanted to know!
    I will make a same research on my pc later to compare the results