- Home /
List Performance Question
Hi! i have a question about, if you could come up with a better optimized way to do this
what it happens is that, my AI cast a sphere, to detects the colliders of waypoints around it, and then save all the detected waypoint colliders in a list, but if you look at the profiler sample, this actions call the GC a lot, and it makes 3% of cpu time from only 6 AIs, is there a better way to do this? does the GC comes from the List.Clear() ? is there a better way?
protected virtual void DetectWaypoints()
{
Profiler.BeginSample("Waypoints");
waypoints.Clear();
foreach (Collider col in Physics.OverlapSphere(this.transform.position, 5f))
{
if (col.tag == "WayPointAI")
{
waypoints.Add(col);
}
}
Profiler.EndSample();
}
Answer by YoungDeveloper · Aug 11, 2015 at 04:48 PM
If there's nothing much happening in your scene, those 3% percent isn't a big deal really, as it's pretty much just a percentage considering everything in the scene. Instead you should look at the spikes and allocation.
Physics.OverlapSphere returns a new collection on each call, so there's really no way you can cache that list and clear() (only List reference). If only you'd write your own overlap sphere.
It's quite funny because if you want to talk or actually optimize things, there much much more than just such visible list clear things. For example, while and primitive for is very very slightly faster than foreach, and strings you are comparing to "Waypoints" and "WayPointAI" - you are actually creating new string each that time. So thats 9*2=18 + 10*2=20 == 38 bytes per frame. So at the end, if you are calling DetectWaypoints() every frame in update, you are generating 38 bytes or useless GC trash every frame, thats aproximately 2300 bytes per second of GC trash.. so... yeah.
thanks, do For and While really are better thans ForEach?
the string Waypoint is for the sample, so that does not counts, and the string i normally store it in a const string on another class
a class that hold all my tags in const strings
DetectWaypoints() is not called every frame, this is called once, every random amount of seconds
so your suggestion is to change For ins$$anonymous$$d of Foreach?
Thats a micro optimization, and doesnt really matter, but if you want to feel better, you can change it :D
Physics.OverlapSphere is being called every iteration. Try calling OverlapSphere once and store the results, then iterate through that.
Collider[] waypointColliders = Physics.OverlapSphere(this.transform.position, 5f);
for(int i = 0, length = waypointColliders.Length; i < length; ++i)
{
Answer by LunaTrap · Aug 11, 2015 at 07:04 PM
I think is just reduced the performance hit on my problem above, thanks to the help from Jessepike and Young Developer
so im answering my self in case someone is reading this in search of an answer, i get this results after changing the code above, to this onem the cpu use % did not changed much but the GC came down from 4KB to 1.4KB
protected virtual void DetectWaypoints()
{
Profiler.BeginSample("Waypoints");
waypoints.Clear();
waypointColliders = Physics.OverlapSphere(this.transform.position, 5f, waypointsLayer);
for (int i = 0, length = waypointColliders.Length; i < length; ++i)
{
if (waypointColliders[i].tag == "WayPointAI")
{
waypoints.Add(waypointColliders[i]);
}
}
Profiler.EndSample();
}
Use GameObject.CompareTag ins$$anonymous$$d of string comparisons.