Search Unity

Performance: CPU vs. Memory / Look-up vs. Recalculation

Discussion in 'Scripting' started by Flame of Endil, Mar 23, 2013.

  1. Flame of Endil

    Flame of Endil

    Joined:
    Mar 22, 2013
    Posts:
    6
    Let me start off by saying that I am not at the level of coding-complexity where every drop of efficiency must ruthlessly be squeezed out of every line of code. My game's just not that big. However, I'd like to learn as much as possible about good coding practices now, so I am prepared when my complexity ramps up.

    Question: when is it better for me to store a value in a variable rather than calculate the value every time it is needed? Is there a general rule of thumb I can use?

    My specific situation at the moment involves the spawning of objects in a grid. Each object will store its "index", which begins at 0 for the first object and increments by one for each subsequent object. For my purposes, the grid may sometimes be resized, requiring each object to adjust it's position relative to the grid origin. I can calculate each object's offset if I know the index, but that calculation involves using Mathf.Floor on the grid's x and y sizes, and multiplying those values by the appropriate amounts in order to determine the object's x and y location in the grid. Would it be better to store the object's x and y location in a Vector2?

    I'm targeting systems from several years back. I know modern multi-core processors can run calculations faster than they can access lookup data from RAM, but to what extent is this true? Does anyone have any references (online articles, books, etc.) about code optimization they can recommend? I would like to look into this issue further.

    Thanks guys! :D
     
  2. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    Depends on how big your grid will be and how frequently you will look up the rotation. If you do it every frame then you might want to consider caching the position. A Vector2 has 2 times a 32 bit float, so that's 64 bits per position. You can do the math based on how much space your grid will take up/ how much you will allow it to take up
     
  3. Flame of Endil

    Flame of Endil

    Joined:
    Mar 22, 2013
    Posts:
    6
    Hmm, okay that makes sense.

    How does a calculation of position (of the manner I described) compare to, say, a GameObject.Find function (that does a string search)? I know that I should cache the results of a Find, because of the amount of processing time it consumes, but how can I know when some other function is beginning to consume similar amounts of processing time?

    Also, is a Vector2 *only* 64 bits? Is there a pointer (or something) involved that would take up memory as well? What I mean is, is there a performance advantage to saying
    Code (csharp):
    1. var gridPosition : Vector2 = Vector2(0,0)
    instead of
    Code (csharp):
    1. var gridPositionX : float = 0;
    2. var gridPositionY : float = 0;
    How much memory/whatever is consumed simply by creating another variable entity?

    Sorry if I'm asking questions that could be answered by a little reading. If anyone knows a good resource to learn about this and similar matters, I would really like to know!
    I've been wanting to pick up a good code book, but I've been discouraged by Unity's "unique" scripting environment.
     
  4. andererandre

    andererandre

    Joined:
    Dec 17, 2010
    Posts:
    683
    Vector2 is a struct, there is no pointer involved and as far as I know a struct is really only as big as its individual members (this is not the case for classes, classes have quite a bit of memory overhead as they all derive from object and, for example, automatically have a monitor associated with them).

    However, structs are "pass by value" so writing something like this:

    Code (csharp):
    1. Vector3 v = transform.position;
    Will copy 96 bits and create a complete copy of the position vector while this:

    Code (csharp):
    1. Transform t = transform;
    Will copy 32 or 64 bits (depending on your OS) for the pointer to the class instance.
     
  5. npsf3000

    npsf3000

    Joined:
    Sep 19, 2010
    Posts:
    3,830
    TBH I think this kind of optimisation is generally irrelevant in C#... the questions you are asking appear more suited to an assembly or C environment :p

    My own rule of thumb is:

    1) Write clean code.
    2) If it takes some computation, and we'll be doing lots of it, and it's easy to cache - then cache it.

    For a grid system - assuming your dealing with substantial numbers of items - I'd usually cache it. Otherwise, I'd write whatever is easiest.

    At the end of the day you need to benchmark - System.Diagnostics.StopWatch is your friend.
     
  6. andererandre

    andererandre

    Joined:
    Dec 17, 2010
    Posts:
    683
    Understanding the difference between struct and class is everything but irrelevant. If Vector3 would be a class, Unity would loose a lot of performance. This is actually a major issue in Java, because the language designers decided to only allow classes and some basic value types, but no structs - leading to a lot of pointer and garbage collection overhead and making the language almost useless for any sort of game development.

    These kinds of questions also lead to a better understanding about what the compiler and language runtime actually do.
     
  7. npsf3000

    npsf3000

    Joined:
    Sep 19, 2010
    Posts:
    3,830
    Worrying whether or not a struct takes up 64 or 96 bytes is irrelevant when it comes to programming a Monobehaviour Worrying about the cost of storing a int pair vs a couple basic calculations that are run at most a thousand times a second is also generally irrelevant.

    While there is some academic interest, I've never seen that be a deal breaker, and I've done some pretty impressive optimisation in my time
     
  8. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Ensure you have a slow test machine to run it on, you can't beat running a built version on your lowest spec target hardware.

    The Unity Profiler is a great help, also there a quite a few Unity specific tricks that can help you optimize check out what people have done to run on older iphones but really it depends on your target hardware.

    Also Unity have an optimization video where they take a Boids implementation and go through a cycle of optimizations it's on the company videos page but gives you some great tips and ideas.

    How often are you Updating your scripts do they need to update every frame, are you using Co-routines and/or InvokeRepeat for code that only needs to run at less than frame rate frequency.

    But after these general Unity tips it's down to how you store and process your data, containers, retrieval, pre-calculated, caching, inner loop optimizations.

    And if you want to start getting more advanced Threading and GPU Compute (DX11).

    Have Fun.