Checking another script on update/Efficiency
Hello All!
I currently have this setup, see below. I've done this for quite a few scripts, but have been wondering if there's a better way, possibly more efficient with less memory usage?
void Update ()
{
if (playerScript.points > 19)
{
if (!spawnedOnce)
{
DoSomething();
}
}
}
Also, just FYI, I'm requesting to find playerScript on Start(). So, what I'm wondering is, is there a better way to approach this? As it stands, it's currently checking/requesting info from this script on another script on each Update(). Surely, I feel there's a better way to do this. Thank you for your help!
For those of us who answer, it is much better to have code formatted text ins$$anonymous$$d of a jpg snapshot, and as much code and context as applies to the question.
Oh sorry, just thought this was more simple for some reason.
Answer by JVene · Jul 24, 2018 at 04:47 AM
Without knowing more about the design, I can only discuss generalities.
In order to perform the comparison like this (it appears to be on an integer), a CPU will load the operand in register, perform a partial subtraction (it discards the answer), then use the CPU flags to decide if the comparison operator results in a true or false statement.
Where it gets the value, and how, is what you're really asking about.
If 'points' were a local or intermediate value, it may already be held in a register (as the compiler optimized), so the comparison just executes.
If 'points' were a local variable on the stack (declared at the start of the function and local to the function), there is a register dedicated to pointing to the stack already, which is used to fetch the value in one step (if it were not held in a register as above).
If 'points' were a member of 'this' class (the owner of Update), there is a presumed register or stack entry identifying the location in memory of 'this' object, where 'points' is known to be some distance from the start of that location - a vector calculating a distance from the top. The CPU would fetch the value from that calculated location. This could be as fast as the previous (local stack variable) if the optimizer loads the 'this' pointer for speed optimization. If 'this' had to be loaded for the memory access, this would be a two step process, one to fetch 'this', the second to fetch 'points'.
Under the hood, playerScript is a smart pointer to an instantiation of class, with a numeric member 'points'. While C# calls them references, they are an atomic value (64 bits on a 64 bit computer) identifying a memory location where the class that owns 'points' can be found (the 'this' pointer for playerScript in this case). The CPU may have to fetch playerScript's location from the current object, then use that to calculate the location of 'points' within that object, making this up to 3 steps in the very worst case, but most likely 2.
This can happen tens of millions of times per second on a phone.
The impact can only matter if this were performed on the interior of a long loop, were thousands or millions of these calls might accumulate a measurable amount of time.
So, if 'point' were accessed inside a loop, it would be best to consider moving that loop to playerScript so it ran locally over there, on playerScript's 'this' pointer, instead of from out here.
But for a single dereference like this, it is not worth effort to alter this when 'points' probably belongs in playerScript.
For another perspective on this, consider the modern cache on all major CPU designs. RAM is connected such that the CPU can read perhaps 20 to 60 GBytes per second on typical hardware. The internal cache of the CPU is wired to read perhaps 500 to 1000 Gbytes per second. Further, when RAM is instructed to switch to a new memory address, the delay is large, sometimes 10, 20 or 30 cycles of the machine. Cache has very little delay. In general operation, code is burst into cache, and looping code will run in cache for a while at high speed. Periodically, though, this gets exhausted because the code must branch to other functions not currently in the cache, so there's a long stall. This happens throughout the execution of software at such speeds humans can never witness it, so we experience the average overall throughput. My point is that the cost of the dereferencing of 'points' vs a local member variable of the same type vs a stack allocated local variable is likely already burst into cache, and may be on the order of 2 or 3 cycles, while other things over which we have very little control can impose 10 or 20 cycles of delay. That said, if 'points' is in RAM not cached recently, that dereference can hit a 20 cycle delay, where a local value would be maybe 2 or 3. However, any reconstruction of your code is likely to cause the same compromise from an opposing perspective. Update, of code this small, runs a grand total of a few dozen cycles at most, and then only at frame flips. There will be a billion cycles of CPU work done between frames before this code becomes a performance cost at all.
If it were inside a loop that took a few hundred thousand cycles, it would be worth considering a refactor.
You do have a good point. I suppose I should have been more clear in my question. playerScript.points is a variable in a different script (it's my scoring on the player object). So what I'm doing here is having this script(Floor$$anonymous$$anager script) continuously(?) check another script (Player$$anonymous$$ovement script).
I addressed that as the 3rd means, merely a few cycles more than a local variable. BTW, these aren't scripts talking to scripts - they're classes talking to classes. Scripts are just text files, where in all other contexts of C# program$$anonymous$$g they are the source files (some say compilation units) of a C# application. The classes are the program$$anonymous$$g concept.
$$anonymous$$y point is that the impact is so $$anonymous$$or in the context of Update that any attempt at optimization is $$anonymous$$or, and the relationship between classes generally causes this type of dereferencing. It is expected and normal.
You are absolutely correct; classes is what I mean to say. It's been a long day. Thanks to both of you, @JVene and @hexagonius. You both have great answers.
Answer by hexagonius · Jul 24, 2018 at 04:51 AM
I would say it depends on the frequency you pass the 19 mark. In my opinion an event in the other class, called when points change, is less noisy. furthermore, since you're trying to spawn something just once, you can then just unregister from the call and nothing is executed anymore. when it comes to performance, absolutely insignificant.
Yes, that's an old, crude trick: whenever you have several tests in a row, arrange them in order of how often they will be false, for an early abort. Or, for an OR-test, how often they'll be true. But never do that for real -- readability is more important 99% of the time. I learned this when running a program came with a bill for how many seconds it took.
Your answer

Follow this Question
Related Questions
Is there a better way to do this? 0 Answers
What is the difference between Update() , LateUpdate() , FixedUpdate(), and when i should use them 3 Answers
get image on url, replace and reload in runtime 1 Answer
Script execution order of child and parent classes - Parent then children??? 1 Answer
Multiple small update calls vs one large update call? 1 Answer