In short, the answer is NO.
My tests showed that using a local variable is always as fast as using a member variable, and usually faster.
Here are some typical results.
Cached: Time elapsed: 00:00:04.8086550 Uncached: Time elapsed: 00:00:09.1058490 Local: Time elapsed: 00:00:04.7870590
They show that caching and accessing the target reference is twice as fast as just using the reference. They also show that assigning to a local variable and using that variable for access is usually even faster than a member variable.
This is the code I used for benchmarking.
using UnityEngine; using System.Collections; public class Benchmark : MonoBehaviour { Transform cachedTransform; void Start () { cachedTransform = transform; TestCached(); TestUncached(); TestLocal(); } void TestUncached() { var stopwatch = new System.Diagnostics.Stopwatch (); stopwatch.Start (); for (int i = 0; i < 100000000; i++) { var p = transform.position; } stopwatch.Stop (); Debug.Log (string.Format("Uncached: Time elapsed: {0}", stopwatch.Elapsed)); } void TestCached() { var stopwatch = new System.Diagnostics.Stopwatch (); stopwatch.Start (); for (int i = 0; i < 100000000; i++) { var p = cachedTransform.position; } stopwatch.Stop (); Debug.Log (string.Format("Cached: Time elapsed: {0}", stopwatch.Elapsed)); } void TestLocal() { var stopwatch = new System.Diagnostics.Stopwatch (); stopwatch.Start (); var t = transform; for (int i = 0; i < 100000000; i++) { var p = t.position; } stopwatch.Stop (); Debug.Log (string.Format("Local: Time elapsed: {0}", stopwatch.Elapsed)); } }
10 comments:
You missed GetComponent() alternative. Which is WAY slower than others:
GC: Time elapsed: 00:01:53.8888645
Still, it should be mentioned for the sake of completeness. I wonder, though, what does GameObject.transform do that is so much faster than GetComponent, but still twice as slow as member access.
I think there is a wrong approach in this test. The results are somehow obvious. I think that the experiment should compare the 3 approaches when using the cached transform in an Update(), where the difference could be obvious if we have to get the reference to the transform at everyframe. Making the test in the Start() proves nothing to me.
No, you don't want to do that. I am testing the speed of accessing variables in different ways from inside a function. To test this single thing, I isolate it and run it inside a minimal loop.
Running in the update function would effectively test everything Unity does per frame, not just a single variable access.
That's right and I understand the results. Caching is worth anyway in front of a general script with Update functions, where don't caching could be noticed.
Interesting benchmark.
I had some doubts at first but indeed you are correct. The local variable approach is the better option if the cached value is used repeatedly.
Anyhow - after a set of benchmarks on my own ( using your code as a basis ) the clear winner with a few loops is the cached transform.
With just a few loops - 1-5 the cached transform is significantly faster ( 35% ). When the loops increase the percentage drops in favor of the local variable ( 30% at 10, the local gets 20% better score on 5000 iterations ).
Even though you results are perfectly correct for a heavy amount of data accessors - in the common case the cached transform is the fastest option.
Hmm, when I change my test to run 5 loops only, I get these figures, which show local access still comes out on top. Can you post your tests so I can compare?
Cached: Time elapsed: 00:00:00.0002060
Uncached: Time elapsed: 00:00:00.0000050
Local: Time elapsed: 00:00:00.0000050
Oh yeah, one thing I forgot to mention - the test ran first is delayed big time.
Anyhow here are some numbers :
Cached: Time elapsed: 00:00:00.0002370
Uncached: Time elapsed: 00:00:00.0000052
Local: Time elapsed: 00:00:00.0000046
All good and shining for the Local variables. But after a quick reordering here is what you get :
Uncached: Time elapsed: 00:00:00.0002386
Local: Time elapsed: 00:00:00.0000051
Cached: Time elapsed: 00:00:00.0000031
Or you get :
Local: Time elapsed: 00:00:00.0002853
Cached: Time elapsed: 00:00:00.0000025
Uncached: Time elapsed: 00:00:00.0000061
There is no obvious reason for this random delay happening on the first test. I've tried delaying the action itself and a couple of other approaches but the issue persists. My guess is that it has something to do with the internal stuff of the Unity Editor.
PS: Your captcha hates me :D
Doesn't using a local variable add to gc hiccups though?
class MyBehaviour : MonoBehaviour {
new internal Transform transform;
void Awake () {
transform = this.GetComponent<Transform>();
}
}
and smile.
Post a Comment