Unity3D: Cache Component References Instead of calling GetComponent()?

You may have heard that you should always cache your transform, gameObject and script component if you plan to access them in your class because this.transform, this.gameObject and this.GetComponent() are slow. But does it really make a difference?

Instead of doing :

void Start()
{
   transform.Translate(1, 0, 0);
}

Should we do the following?

public Transform CachedTransform;
void Start()
{
   CachedTransform.Translate(1, 0, 0);
}

And what about gameObject access and Script Component access with the GetComponent() Method? Let's take a look at some tests. For transform, gameObject and Script Component, we have looped 10 000 000 times on them, once uncached and once with a cached reference. These operations where called from the Start() method and time was measured with System.Diagnostics.Stopwatch.

Accessing Transform (average time in seconds)

Accesing GameObject (average time in seconds)

That doesn't seem too bad. Let's look at GetComponent() now.

Accessing a Script Component (average time in seconds)

As for this.gameObject and this.transform, Unity seems to have some kind of caching behind the scene as the performance difference is not as bad as GetComponent(). However, it looks like GetComponent() is 20 times slower than accessing a cached reference of the Script Component.

Does this mean you should always cache references into a variable? Not necessarily. 10 000 000 GetComponent() calls took 2 seconds, so even if you call it 1000 time per frame, it takes 0.0002 seconds, which is 0.2 milliseconds. Considering a frame at 60 FPS is 16 milliseconds, 0.2 milliseconds is not nothing.

Maybe if you do things in Update(), you should cache references, otherwise, it's not that bad to access it with GetComponent(). As for Transform and GameObject accessing, the caching performance gain is much slimmer. Because of that, the guideline could be to cache Script Component references to avoid GetComponent() and keep using this.transform and this.gameObject because it's simplier. On the other hand, always caching your references doesn't take that much more efforts and optimizes your code from the start.