Author Topic: Garbage collection causing performance hiccup on iOS after updating to 3.6.5.  (Read 3810 times)

schneidb

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 2
  • Posts: 24
    • View Profile
In our game, we're using a pool of NGUI UILabels to display dynamic event based messages to the user.  This was working well, but after upgrading NGUI to 3.6.5, we now get performance hiccup (moment of unresponsiveness) each time messages are displayed.  Connecting the Unity Profiler to an iOS device and recording, I can see that when this happens, there's a GC.Collect spike each time messages are displayed.  Could you elaborate on (or point me to another thread discussing)...

- FIX: Nicki's optimizations.

... as that's the only thing I see that could possibly be related to this issue.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Nicki's optimizations involved replacing Vector3.Min / Vector3.Max / Bounds.Encapsulate functions with code instead, as it turns out to be something like 10 times faster. I don't see what would cause GC in your case. GC happens randomly, and is OS-specific. I suggest looking at what's causing GC to accumulate to begin with. In the profiler where do you see GC allocations occur?

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
I would be very surprised if the optimization I did has anything to do with increased GC.

The concrete code in question is this

Old:
  1. {
  2.         // If there is a widget present, include its bounds
  3.         UIWidget w = content.GetComponent<UIWidget>();
  4.  
  5.         if (w != null && w.enabled)
  6.         {
  7.                 Vector3[] corners = w.worldCorners;
  8.  
  9.                 for (int j = 0; j < 4; ++j)
  10.                 {
  11.                         Vector3 v = toLocal.MultiplyPoint3x4(corners[j]);
  12.  
  13.                         if (isSet)
  14.                         {
  15.                                 b.Encapsulate(v);
  16.                         }
  17.                         else
  18.                         {
  19.                                 b = new Bounds(v, Vector3.zero);
  20.                                 isSet = true;
  21.                         }
  22.                 }
  23.         }
  24.  
  25.         // Iterate through children including their bounds in turn
  26.         for (int i = 0, imax = content.childCount; i < imax; ++i)
  27.                 CalculateRelativeWidgetBounds(content.GetChild(i), considerInactive, false, ref toLocal, ref b, ref isSet);
  28. }
  29.  

new:
  1. {
  2.         // If there is a widget present, include its bounds
  3.         UIWidget w = content.GetComponent<UIWidget>();
  4.  
  5.         if (w != null && w.enabled)
  6.         {
  7.                 Vector3[] corners = w.worldCorners;
  8.  
  9.                 for (int j = 0; j < 4; ++j)
  10.                 {
  11.                         Vector3 v = toLocal.MultiplyPoint3x4(corners[j]);
  12.  
  13.                         if (v.x > vMax.x) vMax.x = v.x;
  14.                         if (v.y > vMax.y) vMax.y = v.y;
  15.                         if (v.z > vMax.z) vMax.z = v.z;
  16.  
  17.                         if (v.x < vMin.x) vMin.x = v.x;
  18.                         if (v.y < vMin.y) vMin.y = v.y;
  19.                         if (v.z < vMin.z) vMin.z = v.z;
  20.  
  21.                         isSet = true;
  22.                 }
  23.         }
  24.  
  25.         // Iterate through children including their bounds in turn
  26.         for (int i = 0, imax = content.childCount; i < imax; ++i)
  27.                 CalculateRelativeWidgetBounds(content.GetChild(i), considerInactive, false, ref toLocal, ref vMin, ref vMax, ref isSet);
  28. }

Which then does a single bound creation and encapsulation at the end of vMin and vMax. The old version which used bounds.Encapsulate for every corner was vastly (factor of 12) slower than the vectors. There are some other places inside NGUIMath where the same thing happened, which was also change similarly. That's the extent of the optimizations


What is your use-case for it, more specifically? Are you moving the labels around before deactivating them? Does it trigger many of the calculations which cause this? What other factors are in play? Take a look at the GC.alloc in the profiler and see what is adding to it. Some amounts of GC is obviously unavoidable, but consistently getting it at a certain point indicates something leaking.

schneidb

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 2
  • Posts: 24
    • View Profile
Hi guys,

Sorry for the tardy response.  I have "notify me" set for this thread, but I didn't get the notification.

Also, apologies for a misdiagnosis.  As it turns out, I was using another Unity add-on and I have now verified that was the culprit.  It was coincidence that I saw a spike in GC.Collect calls after updating NGUI.

Thanks to both of you for your quick responses and your great work!