Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by burtonposey · Aug 11, 2012 at 06:58 PM · vector3optimizationvectorbenchmark

Instance of Vector3.zero faster than Vector3.zero?

I'm currently running an optimization audit on my codebase for my game and noticed Vector3.zero coming up in the profiler. It never really dawned on me that call to that value would have overhead in terms of a constructor and essentially what looks to be a getter in the Deep Profile information.

Here's my test. I wanted to share it with you guys and get your feedback. It's not much at first glance, but on my computer it was about 1 second faster to access an instance variable in the class for Vector3.zeo (vZero in the code below) as opposed to Vector3.zero when testing over 5000 iterations of each test against one another, profiler off. It was actually 5 seconds faster with the profiler on, but that's just miscellaneous information. Even at 1000 iterations, the result was half a second better for the instance.

Just imagine how many places you might end up substituting instances for these convenient, but seemingly not-as-performant vector "getters" out in your code!

 using UnityEngine;
 using System.Collections;

 public class VectorBenchmarks : MonoBehaviour {
     Vector3 vZero = Vector3.zero;
     Vector3 targetVector;
     public int testCount = 5000;
     public int currentTest = 0;
     // Use this for initialization
     void Start () {

         StartCoroutine("VectorTest");
     }


     IEnumerator VectorTest()
     {
         Debug.Log("Beginning test one, Vector3.zero");
         float startTime;
         float endTime;
         startTime = Time.time;
         while(currentTest < testCount ) {
             targetVector = Vector3.zero;
             ++currentTest;
             yield return null;
         }
         endTime = Time.time;

         Debug.Log("End Test One: startTime:" + startTime + "endTime:" + endTime + "duration of test:" + (endTime-startTime));

         currentTest = 0;

         Debug.Log("Beginning test two, instance variable definition of Vector3.zero");
         startTime = Time.time;
         while(currentTest < testCount ) {
             targetVector = vZero;
             ++currentTest;
             yield return null;
         }
         endTime = Time.time;
         Debug.Log("End Test Two: startTime:" + startTime + "endTime:" + endTime + "duration of test:" + (endTime-startTime));
     }
 }
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eric5h5 · Aug 11, 2012 at 11:29 PM 0
Share

The "yield return null"s in there are quite bad for benchmarking, because then you're measuring the time it takes to draw the frame. Remove all coroutines and yields and everything of that nature when doing benchmarking, so you can concentrate on only measuring the thing you're actually interested in. Doing only one operation per frame will get totally lost in the noise; you should do some millions of iterations at once (at the least) to get any kind of measurable result.

2 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by Steel_Arm · Jun 25, 2013 at 08:16 PM

Here is my attempt at this:

 using UnityEngine;
 using System.Collections;
 
 public class VectorProfile : MonoBehaviour {
     float t1, t2;
     // Use this for initialization
     void Start () {
         Vector3 v;
         Vector3 vz = Vector3.zero;
         t1 = Time.realtimeSinceStartup;
         for (int i = 0; i < 100000000; i++) {
             v = Vector3.zero;
         }
         Debug.Log("T1: " + (Time.realtimeSinceStartup - t1).ToString());
         t2 = Time.realtimeSinceStartup;
         for (int i = 0; i < 100000000; i++) {
             v = vz;
         }
         Debug.Log("T2: " + (Time.realtimeSinceStartup - t2).ToString());
     
     }
     
     // Update is called once per frame
     void Update () {
     
     }
 }

Here are my results of doing 100,000,000 iterations of each.

 T1: 2.046641 UnityEngine.Debug:Log(Object) VectorProfile:Start() (at Assets/Core Assets/Scripts/VectorProfile.cs:14) 
 T2: 0.5151472 UnityEngine.Debug:Log(Object) VectorProfile:Start() (at Assets/Core Assets/Scripts/VectorProfile.cs:19)


T1, the first test, uses Vector3.zero. T2 uses an instance of Vector3.zero called vz.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image JChilton · Jun 25, 2013 at 08:54 PM 0
Share

I just ran the same thing.

T1: 1.36627 T2: 0.3786879

That's really interesting.

avatar image BlueRaja_2014 · Jun 26, 2013 at 12:55 AM 0
Share

@Loius: That would require some insane stupidity on the Vector3 author's part; the more natural way would be

 public static readonly Vector3 zero = new Vector3(0,0,0);

Which should be just as fast as or faster than a local variable. $$anonymous$$ost likely, this test just shows (another) awful optimization-fail on the part of the $$anonymous$$ono JIT.

avatar image Immanuel-Scholz · Jun 26, 2013 at 07:36 PM 0
Share

That would require some insane stupidity

$$anonymous$$h....

alt text

property-zero.jpg (5.7 kB)
avatar image BlueRaja_2014 · Jun 26, 2013 at 08:14 PM 0
Share

@Immanuel Oh, I didn't realize Vector3 is a struct (I am new to Unity, though not to C#). In that case, I'd expect all pieces of code to run at the same speed, and in fact that is exactly what I see.

avatar image Loius · Jun 27, 2013 at 01:09 AM 0
Share

Haha, I had my comment up for like ten seconds you speed demon. :)

I said essentially "I don't doubt that .zero is implemented as something like { get { return new Vector3(0,0,0); } }"

It would certainly make sense to do static readonly. I've implemented an integer-only Vector3 and it is so many headaches due to Unity refusing to serialize structs, so I have to make it a class and I've completely lost all touch with how the real V3 works by now. e_e

Show more comments
avatar image
1

Answer by Immanuel-Scholz · Jun 25, 2013 at 09:03 PM

Your performance test is seriously flawed. Here some couple of things that spring up my mind:

  • Use the right tool for the job. Time.time is not meant for precision timing. Use System.Diagnostics.Stopwatch.

  • Always measure in deployed programs, not in the editor or in development builds.

  • Try to minimize the "code under measurement". Especially stay away from heavy noise like rendering frames or starting coroutines!

  • If possible, test the "empty case" as a control group. This measures your test case overhead. If you do the previous point right, this will spill out "0". Also, you will be suprised how often you get an "WTF??" - moment, when the empty case turns out to be slower than the normal case. :-D (If that happens, read up on "JIT compiler in C#")

Sure, usually you skip some or most of these points. If you are sure what you are doing and the performance differences are rather drastical, there is no need for going high-precision.

But in your case, you want to measure 1 second in 5000 iterations, which is 0.2 micro seconds. That is way too short to use a crude Axe-technique.

In the end, Vector3.zero may still be 100 times slower than accessing a non-volatile local member copy (my money is on either "cache faults" or "bad mono 2.6 JIT compiler"), but I really doubt it takes your measured 200µs for every access.

Here is what I did:

 Vector3 vZero = Vector3.zero;
 void Start() {
     var watch = new System.Diagnostics.Stopwatch();
     Vector3 v;
     
     watch.Reset(); watch.Start();
     for (int i = 0; i < 10000000; ++i)
     { v = Vector3.zero; }
     watch.Stop();
     result += "property: " + watch.ElapsedMilliseconds + " ms\n";
     
     watch.Reset(); watch.Start();
     for (int i = 0; i < 10000000; ++i)
     { v = vZero; }
     watch.Stop();
     result += "local: " + watch.ElapsedMilliseconds + " ms\n";

     watch.Reset(); watch.Start();
     for (int i = 0; i < 10000000; ++i)
     { }
     watch.Stop();
     result += "empty: " + watch.ElapsedMilliseconds + " ms\n";
 }
 
 string result = "";
 void OnGUI()
 {
     GUI.Label(new Rect(20, 20, 500, 100), result);
 }


For my machine, it spits out

 property: 120 ms
 local: 21 ms
 empty: 10 ms

So for my measurement, the difference is roughly 100ms for 10 million iterations, or in other words: 1 nano second per access.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image BlueRaja_2014 · Jun 26, 2013 at 08:17 PM 0
Share

This benchmark is still flawed, on two points.

First of all, there is a good chance the optimizer can optimize away the local variable assignment for the second two cases, but not the first (since it is calling a function) - assigning to something like myArray[i] in the loop would be better.

Secondly, you can't test them all in one test, since the JIT could kick in mid-test - you need to test them all in separate executions.

When I do this I find that the local and property tests run at the same speed, on the .Net CLR at least (I don't have $$anonymous$$ono installed AT$$anonymous$$. I do however see the same results as you in the .Net CLR for the flawed test).

avatar image Eric5h5 · Jun 26, 2013 at 10:26 PM 0
Share

You definitely can't go by .NET results, since it has differences and some optimizations compared to $$anonymous$$ono, especially the version currently used in Unity.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

12 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Can't change vector direction 0 Answers

How to change Point of Application of a vector? 1 Answer

Why the object being moved is faster than the rest? 1 Answer

Change direction of vector based on which way player is facing 1 Answer

How to add 2 Quaternions. 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges