- Home /
What more should I be caching within my scripts?
Hello again, guys.
I recently found a good thread here about caching GetComponent calls, since they're apparently fairly slow. Since then, I've been scanning all my code for such calls in Update and elsewhere and replacing them with cached variables wherever it's possible to do so.
My question, though, is this: Should anything aside from "Get"s be cached? For instance, if I want to rapidly assign an intensity value to a light within Update, should I cache my gameObject.light into some sort of MyLight variable to enhance performance, or are these not the same as GetComponent calls?
Answer by Eric5h5 · Nov 11, 2011 at 01:03 AM
GetComponent is not really slow. If you're only accessing it once per frame, caching it is not going to make any measurable difference (a decent CPU could do 10+ million GetComponent calls per second), so it's not likely to be worth using up more memory by caching it. Anyway, "`gameObject.light`" is the same as "`gameObject.GetComponent(Light)`". I'd only bother with caching if you're heavily using that component.
The various Find commands, on the other hand, are always worth caching.
Cool, thanks. Obviously this could apply to anything, but I recently wrote a light flickering script where a light's intensity is altered every frame so I wondered if I was wasting my time caching or not. It's good to know that any reference to a component is essentially a GetComponent.
on platforms like Windows Store where you are going from a strict secure managed boundary to native code in the unity engine potentially many times a second, this is an expensive operation and if you can cache objects in script, it can really help.
It is really slow. Consider making a game, where the target frame rate is 60. That gives you 16 ms to work with.
Only 10,000 calls in one frame to GetComponent will consume 1 ms of that 16. 1/16 of your latency budget is a big deal, and that's just on GetComponent calls, setting aside everything else. 10,000 calls may sound like a lot, but you'd be surprised how quickly those 10,000 can get consumed if you're careless.
Honestly, it is fairly silly in my opinion that simply getting a component is slow. It should be no slower than iterating through an array of references to components and returning the first one of type T. Of course, we can't access that array, as it's hidden away in C++ land somewhere.
It's not really slow. 10$$anonymous$$ GetComponent calls isn't even remotely 1ms:
Also, being "careless" isn't an acceptable program$$anonymous$$g practice, regardless of GetComponent speed.
Thanks for posting that image and keeping the title as 'profiler'. I was wondering what Unity had in the way of optimisation tools... I've just been running blind until now.
...and in the response to the comment above that resurrected this question...
Whilst it is obviously better practice to cache things and generally just make the script neater and easier to read the effect on frame rate really isn't going to be remotely noticeable on any modern computer, probably not until you get into the hundreds of thousand or millions of calls per frame mark.
When I started I had hundreds of objects running FindWithTag on hundreds of other objects every single frame and then running that array through distance calculations. Now I have nothing using FindWithTag and a large chunk of those calculations done on a single object only when called. Fairly hefty optimisation I thought... I saw no difference at all in FPS and barely a thing in CPU usage. If thousands of FindWithTag calls running every frame doesn't make a noticeable difference to performance a mere 10,000 GetComponent calls isn't going to do a thing...
Answer by Rod-Green · Nov 10, 2011 at 11:45 PM
The rule of thumb I go by is if you're accessing any component in an update loop then it's best to just cache it locally to prevent any 'find' operation that might be hidden by a property Get. I.e. this.transform (might or might not) refind the transform every time it's queried. So to be safe it should be cached.
"this.transform (might or might not) refind the transform every time..."
Is this true?
No. It will get the component every time, but as I explained in my answer, it's usually not that big a deal.
As Eric pointed out it will get the component every time. However I've heard that unityEngine will cache some of the queries but you can't really be sure.
Saying this is an unnecessary optimization might be a little extreme. Given that hardware is fast it of course might be able to do millions of lookups perframe unloaded but in reality with everything else this can be a good place to optimize performance. Also the memory associated with storing a local property pointer to an object is pretty much non existant.
http://unity3d.com/support/documentation/ScriptReference/index.Performance_Optimization.html
Another optimization is caching of components. This optimization unfortunately requires a bit of coding effort and is not always worth it. But if your script is really used a lot and you need to get the last bit of performance out of it, this can be a very good optimization.
Whenever you access a component through GetComponent or an accessor variable, Unity has to find the right component from the game object. This time can easily be saved by caching a reference to the component in a private variable.
As I said in my original post this isn't really a 'rule' but more of a 'rule of thumb' meaning in some cases it's great in others it's unneeded. Without any direct issue it's hard for us to give you good meanigful optimization advice.
However have you tried running the build through the profiler and looked to see where the cycles are being spent? I.e. turn on record and deep profile and you'll quickly identify any obvious performance issues*.
*Profiler has significant overhead so some methods are represented more expensive than they actually are. It's more of a guide to show what methods are called most and where they spend most of their time.
I didn't say it was unnecessary. Note that the docs you quote specifically say "not always worth it". The point is that going crazy trying to cache every GetComponent call is counterproductive. Also, those docs are from the days when GetComponent was more expensive than it is now.
$$anonymous$$eep in $$anonymous$$d that I don't have access to the profiler, otherwise I'd have done a deeper test myself. :)
Answer by DaveA · Nov 10, 2011 at 11:38 PM
Yeah, any 'Find' operation for example is a good thing to do once.
Your answer
![](https://koobas.hobune.stream/wayback/20220613040930im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Saving variables? 3 Answers
Change all value of variable 1 Answer
How to set/get/change variables for newly spawned gameObjects? 1 Answer
2 small questions about scripting 1 Answer