Author Topic: Massive GC Spikes ('batting' UIPanels)  (Read 5489 times)

doggan

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 13
    • View Profile
Massive GC Spikes ('batting' UIPanels)
« on: March 03, 2014, 04:08:51 AM »
Hello.

It seems that UIPanel stores it's vertex buffers as static, meaning they are shared between all UIPanels. The comment in code says 'Cached in order to reduce memory allocations'.

This creates massive performance issues when two or more panels are active at the same time, and they both have some animated widget that requires redraw.

For example, Panel A is a normal panel and Panel B is a sub-panel set up with clipping for a UITable or UIGrid. They are both active at the same time. In both panels A and B, you have a UILabel that animates its color every frame. This animation forces both panels to re-draw and rebuild their buffers every frame.

Since the buffers are all using NGUI's BetterList, they theoretically should be re-used and therefore minimize allocation. But the problem is exacerbated when the vertex count of Panel A and Panel B is very different.

For example, Panel A has 100 vertices and Panel B has 2000 vertices. When the panel submits its draw call (UIDrawCall::Set), setting the mesh's vertices requires calling BetterList::ToArray, which is then forced to call BetterList::Trim to resize the buffer.

When Panel A and Panel B get updated every frame, they will basically fight one another for the shared (static) UIPanel vertex buffers. Panel B will constantly need to re-alloc a larger buffer for 2000 vertices, and Panel A will constantly need to trim down to 100 vertices, causing large alloc and GC problems.

I've temporarily solved the issue locally by removing the 'static' modifier on the UIPanel's buffers. While this technically increases my initial alloc count, it gives me much smoother and stable performance overall.

Is there a better way to solve this issue (other than not animating the labels...)?

Thanks! :)

GavinWoods

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 10
    • View Profile
Re: Massive GC Spikes ('batting' UIPanels)
« Reply #1 on: March 03, 2014, 04:48:23 AM »
Seems we both have the same issue here. Although removing the static fields only spread out the alloc's for me. Still better than every few frames I suppose.

If you only need to move something I found its less stressful to move a panel with 1 object. It doesn't solve issues of scaling and animating though,

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Massive GC Spikes ('batting' UIPanels)
« Reply #2 on: March 04, 2014, 12:37:33 AM »
That's a good point, doggan. I'll make the same change on my end. In fact, I can probably just move the buffers to the UIDrawCall, then they will be per-draw call, further reducing allocations and likely resolving Gavin's issues as well.

Edit: Done. In the Professional repository now. All cached buffers are now per-draw call.
« Last Edit: March 04, 2014, 12:51:14 AM by ArenMook »

GavinWoods

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 10
    • View Profile
Re: Massive GC Spikes ('batting' UIPanels)
« Reply #3 on: March 04, 2014, 02:16:55 AM »
Thank you so much for the quick resolution. The games much more stable now.