- Home /
Should I create local copy of global variable?
I've got a little script that tracks player input, which can be accessed in other scripts via global variables. Is it fine to just keep calling e.g., ControlInput.movement multiple times in those scripts, or is it better for performance to copy the global variables into a local ones for the purposes of that script?
Sorry, bit of a noob question. It might make no difference at all. Just trying to learn best practices. =]
That's odd. If anything, I'd guess static variables perform better than local.
@Cawas, you may be right: according to the $$anonymous$$SN docs, the instructions used in member variables (Ldfld and Stfld) receive an indirect reference to the variable (a pointer to a pointer to the variable), while the instructions that handle static variables (Ldsfld and Stsfld)) receive a direct reference (a pointer to the variable). This makes a negligible difference, of course, but static seems a little (very little) faster.
Cool @aldonaletto ! I know nothing about those "instructions" but... Does it being slightly faster have anything to do with static needing no instantiating compiler-wise?
Answer by aldonaletto · Apr 04, 2012 at 03:20 PM
Not a noob question - on the contrary, that's a very interesting one! I was just wondering myself about this same subject, and decided to use ILSpy to check the CIL code generated for static and member variables.
It seems that there's no gain in caching static variables: both, member and static variables are accessed with a single instruction - ldfld for member variables, ldsfld for static ones. These instructions are interpreted and executed in native machine code, but for sure there's no significant difference in CPU cycles - it would be a lot different if several CIL instructions were needed to access static fields, what's not the case.
You can see below the significant part of the simple JS code converted to CIL, with comments linking the CIL instructions to the JS ones:
Script CheckVPort.js:
static var vStatic = 0;
Script Zoom.js:
var vLocal = 0;
function Start(){ vLocal += 1; CheckVPort.vStatic += 1; } The same Zoom.js compiled to CIL:
//var vLocal = 0; .field public int32 vLocal
//function Start(){ .method public hidebysig virtual instance void Start () cil managed { // Method begins at RVA 0x88e0 // Code size 27 (0x1b) .maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
// vLocal += 1; IL_0002: ldfld int32 Zoom::vLocal // read int variable vLocal... IL_0007: ldc.i4.1 // load constant 1... IL_0008: add.ovf // add constant to it... IL_0009: stfld int32 Zoom::vLocal // and store in vLocal // CheckVPort.vStatic += 1; IL_000e: ldsfld int32 CheckVPort::vStatic // read int static vStatic... IL_0013: ldc.i4.1 // load constant 1... IL_0014: add.ovf // add constant to variable's value... IL_0015: stsfld int32 CheckVPort::vStatic // and store in vStatic IL_001a: ret } // end of method Zoom::Start //}
Well actually, the fact that there is only one CIL instruction does not mean it is the same number of CPU cycles. And CIL instructions hide V$$anonymous$$ optimizations such as caching and registering.
But as you pointed out, the difference might be too thin. It is better to put all effort on algorithm and data structure than on this kind of subtleties.
And I agree: not a noob question ;)
@$$anonymous$$riptos, you're right: maybe "execution time" would sound better than "CPU cycles". In fact, the fetching, interpretation and other jobs executed for each CIL instruction often take more time than the actual machine code - a price to pay for the safety and portability of CIL code. But the main objective was to check if member and static variables were accessed by similar instructions, what they in fact are (even the instruction sizes are the same, 5 bytes).
Answer by Kryptos · Apr 04, 2012 at 02:16 PM
From a conceptual point of view, this makes no difference. From a more practical point of view, this is harder to tell. Local variable may be on the stack, i.e. very close to the code using it. On the other hand variables from other script can also be cached into registers.
Although C# (or JS) runs on a virtual machine (Mono), these concepts are pretty much the same as code running on a CPU (such as C/C++). But this depends exclusively on the implementation and design choice of the VM. As game developer we can't do anything about it.
Regarding games made with Unity, I don't think it's making any difference. You don't have the same constraints as realtime-guaranteed applications. So just use the way that fit your coding habit.
You can do much better optimization by choosing the right algorithms and data structures.
Answer by clfischer · Apr 04, 2012 at 01:49 PM
I've read that it's a lot faster to access a public variable from another class directly (ControlInput.movement) than to make it private and call an accessor function (ControlInput.GetMovement()). Not necessarily as tidy in terms of encapsulation but faster. However, I don't know if there's any difference between getting a variable from another object or from the current object. I expect it performs pretty much the same.