Vector3 name = new Vector3() vs. Vector3 name.set() ... which is faster?
Hi there,
I'm relatively new to coding (particularly in c#), but recently saw two different ways of setting parameters in a Vector3, as follows:
Here's what I wrote initially;
public class Player : MonoBehaviour {
void FixedUpdate()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
Vector3 movement = new Vector3(h, 0f, v);
Move(h,v);
}
Simple enough and works just fine. However, I then saw someone else write the same behavior with the following;
public class Player : MonoBehaviour {
Vector3 movement;
void FixedUpdate()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
movement.Set(h, 0f, v);
Move(h,v);
}
So, without having any insight as to what's happening behind the function/method, it appears (on the surface) that the first version is re-creating a Vector3 from scratch during each fixed update, while the second example is changing the value of an existing one.
My question, quite simply, is does one have a performance advantage over the other? I realise that these examples will have a tiny performance overhead, but it would be good to know for more complex code where similar instructions might be running dozens of times simultaneously.
Thanks in advance for any insight anyone might have.
Answer by Owen-Reynolds · Aug 08, 2015 at 01:26 AM
This is a good example of why these things aren't even worth thinking about.
In the first code snippet, movement
is never used. Line 7 could just be deleted. The second code snippet probably never uses it either (it's a global, so someone else might. But since it was local in the first snippet, it probably useless wastes space.) And, it appears to always set y to 0. So movement.x=h; movement.z=v;
would be faster (but harder to read?)
Thinking about what might be a tiny speedup (or might be a tiny slowdown -- it's like all those shortcuts that aren't really) makes you miss obvious stuff, like logic errors, or very slow code.
As for new
, you can read about the tricks C# uses for very short-term garbage, when a new
doesn't make anything.
Answer by Sethery88 · Nov 21, 2019 at 04:52 PM
well, by logic (i really dont know, but im going to try) i believe the second one would be faster, as it creates the variable once, and assigns it every update, whereas the first creates and assigns it every update.
keep in mind i dont really know, and this might only be a thousandth of a millisecond faster anyway, if it is at all
if you downvote my comment, atleast tell my why, so i can learn ins$$anonymous$$d of you going "nah" thx
it wasn't me, but probably because you've dug up a 5 years old question :)
yeah maybe, but i still dont like when people say somethings wrong without telling me why. I like to learn this stuff, ya know?
Answer by Ermiq · Nov 21, 2019 at 05:39 PM
It depends on the internal Vector3.set()
implementation.
Basically, if we assume that 'Vector3.set()` doesn't create a new object behind the scenes, than it will be faster.
Because when you use Vector3 name = new Vector3(1, 2, 3);
you tell the compiler to create a new object and to assign it to the variable name
. It doesn't even matter if the Vector3 name
is local or global, by using new
you create a new object everytime, therefore it requires a memory allocation everytime. A lot of people think that if they declare a variable as global (i. e. have cashed the variable) than it's already all fine and they are assured that now they could freely use it in Update()
and FixedUpdate()
loops. It's not entirely true. If you use new
keyword (even on the global variable) you create a new object and you trigger memory allocation in the heap everytime.
So, assuming that Vector3.set()
just changes the values of the existing object and there's no new
involved than it could be considered to be faster because it doesn't require memory allocation.
It turns out this Q is several years old. Someone (why?) added a reply today, which popped it to the top of the list.
As for "new": Vector3 is a struct, so the "new" is fake. C# has funny rules like that.
There is no need to assume anything. Set is exactly there to set values in place, as per documentation.
Structs are particularly weird in C# anyway and require some getting used to. They mostly (but not always, depending on their usage) live on the stack, thus their allocation is really fast, also they cannot be inherited (or inherit other structs or classes), and are treated as primitives, meaning that they are copied around, unlike objects whose heap references are passed ins$$anonymous$$d.
However, it gets really complicated once you start tackling with the principle of immutability, and access modifiers such as ref and in (in arguments), and declarative ref. I recommend you read a lot on these subjects (here I'm just assu$$anonymous$$g that you haven't already, I'm sorry if I'm mistaken) -- it's worth exploring it for performance reasons, and of course, it's always good to have a better comprehension of C# under the hood.