Lack of inline optimisation?

BTW - where is the documentation tag, please add! And one for optimization?

OK anyway is this page of the docs still fully relevant for optimization?

It says " The primary issue here is that Unity performs very little method inlining, if any. Even under IL2CPP, many methods do not currently inline properly. This is especially true of properties. Further, virtual and interface methods cannot be inlined at all."

Now I don’t prematurely optimize and it may never be needed but the idea that you should cache your list count to use in a for loop is a bit of an annoyance (pre-il2cpp I actually though this was a de-optimization because the compiler does not know you are staying in the list/array bounds…). Also when Properties are the most common way to provide variables in place of public fields, if the compiler can not optimize out any overhead of a property call (particularly an auto property) it is also problematic (and not very clever in these AI times)

I notice a lot of Unity’s vector classes use [MethodImpl( MethodImplOptions.AggressiveInlining )] on properties and functions so is this a speedup?

Further more if Vector3.zero being implemented as a property is a potential issue, why don’t you implement it as a public variable?

As far as I remember this has always been a best practice optimization even in plain C# to avoid the property access for every loop iteration. In C++ this can be optimized by the compiler but there aren’t any guarantees as far as I recall. Even the CPU may optimize this under some conditions but not sure if I recall this correctly.

In any case, that’s a micro-optimization.

It can be. C# does not guarantee the inlining actually happens, mostly if the method in question is non-trivial inlining will not be done.

I believe Vector3.zero is a static field, not a property.

Incorrect. Why it is a property I am not sure…

public static Vector3 zero
{
	[MethodImpl( MethodImplOptions.AggressiveInlining )]
	get
	{
		return zeroVector;
	}
}

The docs seem technically
wrong here as they say it is implemented as get { return new Vector3(0,0,0); }

I mean you can see for yourself in the source code reference: UnityCsReference/Runtime/Export/Math/Vector3.cs at master · Unity-Technologies/UnityCsReference · GitHub

It’s a property pointing to a static-readonly field, so the docs there are probably a bit out of date. Though naturally a property pointing to a static-readonly field is going to be more performant than a property that constructs a new instance every times it is accessed.

Why a property? Who knows. If the underlying implementation needed to change then that’s only possible with a property rather than a field. Of course the overhead of a method call is trivial unless you’re talking about thousands upon thousands of iterations, where you can just cache your Vector3.zero value beforehand.

I gave up worrying about these kinds of optimizations back when Unity released ECS. You might be able to get a 2% increase by using these optimizations or a 10,000% increase from ECS. Honestly though, most games dont really process much gameplay data. Most of the CPU will be processing skinned meshes, physics, pathfinding, AI etc so your game code has very little effect. Even Unreal blueprints are about 5-10% slower than c++ but it’s not worth the effort of using c++ most of the time.

The only time it might be important is if your game has thousands of units or maybe you want to reduce a mobile game’s power consumption. In which case ECS is still a better option. I’ve never had a need for this and I don’t like working with ECS so I just stick to standard Unity monobehaviours.

About the only optimization I do look out for is reducing garbage collection as it can cause lag spikes.

3 Likes

Agreed the optimisations are not a concern in general, but if Unity does a section on optimisation and points out its own possible shortcomings you can question them, or the advice they give!

I mean in their own article it says:

In some projects, even Unity’s built-in trivial properties have been replaced with static readonly variables, resulting in small improvements in performance.

So they took their own advice and improved the properties for Vector3.zero and Quaternion.identity, among many others.

And same old story with documentation, if you see something you think if incorrect, report the page. I just did so.

1 Like

This is probably the first and most important ‘optimization’ anyone should learn when using Unity. DOTS also has its place but let’s be real - very very few games actually need that level of optimization. For the ones that do, the devs probably already know and already have started working in that way.

I’ve only ever twice actually seen a slight performance issue from function call overhead and in both cases it’s because I was iterating over tens of millions of entries in a very tight loop with single-line accessors as function calls. In both cases, simply removing some abstraction via a couple nested function calls and hard-coding the same logic in multiple different functions ended up fixing the problem. Probably a much bigger boost would have come from redesigning my code to use a background thread but I just couldn’t be bothered at the time. A two minute fix worked just as well and since I only called it once in a while it wasn’t worth the extra effort. Would it be nice if inlining was a thing? Sure. Is it often that it becomes an issue? Well… I still find the Animator, physics, skinned meshes, and rendering in general take up 60-80% of all my frame time.

3 Likes

Well… there’s the thing. Do enough people use/need DOTs to make it worth the huge effort?
You don’t see many RTS games these days because they used to be so CPU intensive to develop (and graphically), but these days it is usually the graphics that are limiting the frame rate (I imagine).

I mean DOTS isn’t only about performance. It’s also another way to handle game architecture.

Still, going off SteamDB, plenty of games are using the tech: https://steamdb.info/instantsearch/?refinementList[technologies][0]=SDK.UnityEntities&refinementList[technologies][1]=Engine.Unity