#Lane Player Optimisation

1 messages · Page 1 of 1 (latest)

proven whale
#

How many iterations does this for loop generally go through then?

#

and please clarify what StartEaseX.Get(x) does

buoyant onyx
#

Some custom-written Easing library using IEaseDirective

proven whale
#

Another question, is LaneStep a class?

#

Hmm okay maybe not so bad then. Its hard to identify what is contributing most to 9ms (did i read that right?)

buoyant onyx
proven whale
#

how large is the list/array its looping over generally?

buoyant onyx
#

is that something I need to find out with a debugger

proven whale
#

Erm if you dont even know then yea?

#

If its many thousands then thats important information

#

cache locality starts to be important and you may then need to start using a struct instead of a class

buoyant onyx
#

well I hated to attach debugger, because it doesn't keep my external editor config (rider) on restart, it either resets to VSCode (which I will consider uninstalling) or none

buoyant onyx
proven whale
#

structs are value types vs a class which is a reference type
a list of a class is just a list of pointers, a list of structs however is a list of that struct object. This is good for cache locality because the objects are all next to eachother and this reduces "cache misses".
These are more advanced topics and are often harder to understand in managed languages like c#

#

If you know c/c++ or other native languages then this may make more sense

buoyant onyx
#

because it's fundamentally user-submitted datas

proven whale
#

Then stop and find out what data you are profiling with

#

Pretty important information to know

buoyant onyx
#

I really barely understand what's happening >.>

buoyant onyx
proven whale
buoyant onyx
#

just 2

proven whale
#

Then how many itterations does this for loop run for?
for (float x = Mathf.Floor(progress * 16 + 1.01f) / 16; x <= 1; x = Mathf.Floor(x * 16 + 1.01f) / 16)

buoyant onyx
#

even dragged it to the part where it struggled for decent frametime

buoyant onyx
proven whale
#

and how long is this "mesh lane step looper" section taking?

buoyant onyx
#

the entire marker?

#

or that loop in particular?

proven whale
#

the section, if still too long add more markers to help finding the specific cause

#

I cant tell myself just yet

buoyant onyx
#

the same part I put the breakpoint in

proven whale
#

so 9ms for the marker, 7 to call AddLine() and 3ms for the actual list addition
Did it really run List.Add() 24k times???

#

I cant see the column headers

buoyant onyx
proven whale
#

well UpdateMesh is called 995 times in 1 frame which sounds pretty excessive

#

may just be that too many LanePlayer objects are updating at once

buoyant onyx
#

because the scene in question has ~30 ish lane in render :v

proven whale
#

I have soo many questions, why are 900 updating in 1 frame? do they need to update each frame? is this only needed once on Initalisation?

buoyant onyx
#

(the designer really pushed it to the limit 😔 )

proven whale
#

Entities may be good for you here if you need to process 900 of these a frame but depending on how the "mesh" is updated or changed you may be fucked either way.
Can you explain with more detail what LanePlayer update mesh is really doing?

buoyant onyx
#

(this is the entire function with the comments of explanations (before adding the profiler markers))

#

(sorry didn't bother pushing to a paste-site, since it's already uploaded here prior, so yeah)

proven whale
#

to be updating the mesh and reuploading each frame 900 times is poor design and may not be viable

buoyant onyx
#

-# I mean, I'm just a maintainer, I didn't create this mess, honestly

proven whale
#

Then what was the state of this performance wise before and what have you done and been tasked to do?

buoyant onyx
#

LanePlayer's UpdateMesh is the most tricky to deal with so far

proven whale
#

There are many general things you can do to get some free performance
first you can have 1 monobehaviour manager that manually "updates" these instances instead of using say Update/FixedUpdate 900 times
Secondly you can think more about struct usage to greatly speed up some loops that interact read and write to collections a lot.
Thirdly try to refactor away RemoveAt(0) because this will shift up ALL other elements, if required you should remove a large range in one go to perform that shift up once.

#

Also try to keep a local reference to Transforms used more than twice because there is a cost in retrieving the component via the .transform property

#

(This is because many functions and properties go to a native engine function and this has a small cost)

buoyant onyx
proven whale
#
//Do
Transform otherTransform = thing.transform;
otherTransform.position = Vector3.zero;

//Instead of
thing.transform.position = Vector3.zero;
#

May help here:

            JudgeLine.transform.localPosition = (startPoint + endPoint) / 2;
            JudgeLine.transform.localScale = new Vector3(Vector2.Distance(startPoint, endPoint), .05f, .05f);
            JudgeLine.transform.localRotation = Quaternion.Euler(0, 0, Vector2.SignedAngle(Vector2.right, endPoint - startPoint));
buoyant onyx
#

won't it add an overhead from allocating an array/list on execute?

#

or would that outweight the current implementation's overhead itself?

#

(outweight might not be the right word, I meant it the other way)

proven whale
#

I dont know were you got that from

#

removing a range is better because we can remove AND move up the elements after at the same time

#

if you remove an element in a list and its not the last, all other elements get shifted -1 to fill the empty space

#

1,2,3
remove 2
1,-,3
shift up
1,3,-

buoyant onyx
# proven whale removing a range is better because we can remove AND move up the elements after ...

is this good enough?

//...
            sr_TimestampRemove.Begin();
            // Remove timestamps and position points when we already move past them
            while (TimeStamps.Count > 2 && TimeStamps[1] < time)
            {
                _RemovingTimeStamps++;
                _RemovingPositionPoints++;
                _RemovingLaneSteps++;
            }

//...

            sr_MeshUpdater.End();
            
            if (_RemovingTimeStamps == 64 && _RemovingPositionPoints == 64 && _RemovingLaneSteps == 64)
            {
                TimeStamps.RemoveRange(0, (int)_RemovingTimeStamps);;
                PositionPoints.RemoveRange(0, (int)_RemovingPositionPoints);
                Current.LaneSteps.RemoveRange(0, (int)_RemovingLaneSteps);
                _RemovingTimeStamps = 0;
                _RemovingPositionPoints = 0;
                _RemovingLaneSteps = 0;
            } 
#

(dont ask why I'm casting to int, I was sleepy)

proven whale
#

That while loop will never end, take a good look again

#

You need to re do it to calculate the amount of elements to remove in a better way

buoyant onyx
#

I guess I didn't catch it because it was updating in a coroutine

buoyant onyx
proven whale
#

For large lists it does matter

sage wyvern
proven whale
#

dont think line renderers are used here (for some reason)

sage wyvern
#

Well, whatever they're using, it doesn't sound like 900 iterations of this logic needs to run at the same time.