UMG/Slate Binding Property or Function - Performance differences

Hi,

I’m not so familiar with UMG Binding and I’m wondering if there are some differences in term of performance between Function or Property bindings.

Let say you have:

FText MyBtnText;
FText GetMyButtonText();

If I bind one of the other, does the process is the same.

I mean for the function, I know that GetMyButtonText will be called at any tick() when the widget is rendered.
For the property, does UMG/Slate read it at each Tick like the function and it’s the property that raise an event to all “Bound” delegates and the Widget Value is updated ?

For me, it’s really important if the 2 type of binding are not managed identically.
For example, if you MyBtnText only changed on a “specific event”, the Binding will only be called 1 time per “specifice event” instead of all tick!

Thanks,

I did find some information about it that I can extrapolate to “Behave the same”.

In fact, if you bind on Property, in fact you are binding on a “TAttribute<>” which create a GetAccessor(); so it’s a function :smiley:

Loop is done, binding on function or property is the same, it’s all end in binding a function.

Can someone confirm?

Thanks,

Well as all performance related questions: do a benchmark and compare. :]

I’m pretty sure both will be called each tick, and the slight difference between properties and function calls are probably not noticeable. Let us know what you find. :slight_smile:

1 Like

Binding Performance Order (Fastest -> Slowest)

Property Binding
C++ Function
Blueprint Function

Property bindings are function calls, but they go through a specialized fast path that calls only native code and looks up the data using reflection, caches a buncha stuff…etc. They’re like an order of magnitude faster than binding to a blueprint function.

All bindings are evaluated at least once per tick, some are evaluated a couple of times, e.g. Visibility.

All that said, it really doesn’t matter, all the binding options are much slower than setting the value directly. So if you need performance, avoid binding all together, set the values directly on the widget.

3 Likes

Thanks for the update. I’m really surprised by what you are saying. So if I’m using UMG for my HUD, I should set the value in the tick function instead of doing binding because it’s a lot faster… I didn’t knew it.
So Binding is great when not expecting big performances (Menu) but for HUD, we should consider the old way in the tick function, is that right?

In term of implementation, I’m trying to do the most of the workload in C++. If I want to set back a value to my widget, what’s the best approach:
1 - Create a event that will pass & set the value in the Widget
2 - Get a reference to widget and set it when you need it in C++ code directly?

I’m in 4.8.1 as of now, and my HUD in UMG is taking about 10% of my fps so I’m looking for optimisation path.

A side question on performance, should we put most of the component inside 1 widget or dividing your Hud in** multiple widgets** (by roles like player information, minimap, score etc…) won’t impact the global performance.

Thanks,

By setting the value directly I was implying not to do it in tick. If performance matters you should do as little tick work as possible. That said, setting it every tick from blueprints is probably faster than a blueprint binding, but slower than a native binding.

Every widget costs layout overhead. It’s up to you to strike a balance between separation of concerns and efficient rendering. e.g. I would never have every dot on a minimal be another widget. But I make the minimap be its own widget.

Would it be possible to use the FPropertyTracker to monitor when vars change and only update the binding then?

Whatever FPropertyTracker is, it’s no longer in the codebase. I’m assuming something to do with network replication? If so, I’ve considered it, but only in passing. I’d need a bunch of time I don’t have to prototype something like that :slight_smile: But the idea had crossed my mind. I’d have to introduce a new tracking flag type, don’t want to replicate things just to monitor them in the UI, but in theory it could be efficient.

Still, if performance matters, a human making an event based notification layer for the UI will always be better for performance.

Thanks Nick, it’s great to have developer insights.
It’s always the chicken and eggs story.

I will keep your advice and try to move forward from here. I think I will put event in my code for Data that do not change often.

Are you using UMG yet for production games like Fortnite?
As of today, none of the templates, neither UT4 is using UMG for HUD and it lets me think that it’s not ready yet for AAA production.
I know that you are working on it so it performs better but did your reach the level of AAA UI performance?

We’re using UMG in production for all our games (menus and HUDs). All except for UT; they started before UMG could barely walk and they’re a very small team. So it doesn’t make a lot of sense for them to go back and rewrite something that is working for them. Additionally the UT frame rate target is 120Hz, so they’re VERY concerned about performance and are being very risk averse by choosing an old standby like AHUD/Canvas. Updating samples takes a lot of time and resources; should we find them or need to make a new sample, they’ll be using UMG.

Depends on how complex your UI is. We’re still working on it, so it’s not where we need it to be, but it’s plenty there for some uses cases.

Excellent news.

My UI is not so complex (I have to display 5 pawns data out of the classic score, minimap, main player information) but as of today it is taking too much on my Frame time. Most of it might be due to the fact that the UI implementation is clearly rough and not optimized. This was the purpose of this thread to learn how to deal with performances & constraints with UMG binding :smiley:

On UI/Hud, how can I measure if using Material Parameter to update things like progress are slower than using UMG Progress Widgets?
Does Stat Slate will give me the information or should I run the profiler ?

Using a material on an image for a progress bar is faster on the CPU, probably a little slower on the GPU. With the new invalidation panel using a material is even better, as updating material parameters does not require an invalidation of the cached widget geometry / vertex buffer batch data, where as changing the progress bar would.

The profiler just uses the stat system. So it’s the same information, profiler just keeps a history, and doesn’t have the overhead stat slate does. If you use stat slate, you’re artificially increasing your UI time, because drawing the stats is part of slate’s draw time.

Personally, I use “stat dumpave -num=120 -ms=0 -root=stat_slate” in the console, it will dump out to the average of 120 frames of slate stats to the Visual Studio output.

Thanks for those useful information and console command I bet I will do a good use of it :smiley:

Do we have some detailled information on the invalidation panel on what’s make it “invalidate” a widget or not?

Let’s says you have a score Text that go fom 0 to 1000. Is it better now to size the Textbox width so it’s not linked to the content so even if we change the text, the widget is not invalidate?

Does Image Hide/Visible can invalidate? I bet Collapsed will.

Does UMG/Slate still do a Atlas map of all images to limit draw calls or is this something we should manage by merging some material together (like Progress bar + progress bar background) to avoid to set 2 image widgets with transparency on top of each other ?

Thanks,

What is it ?
TAttribute<> ?

All bindings are TAttributes, the difference is what the TAttribute is hooked up to.

Anything that changes the visual appearance of the widget requires it to be invalidated. The only exception to this is changes to appearance that are not stored in the vertex buffer for the widgets, e.g. Materials. Changing a material parameter does not require invalidating the widget.

All of those changes require invalidation. If they change often, consider just making the widget volatile.

UMG does not atlas things, just batches, we need a different approach to handle UTexture atlasing.

I bet this is something new with the invalidation panel? Is it a property on the Widget itself?

I’m not familiar enough with this, but does that means that the image are sent by “bucket” and not one by one to the graphic card and that limit the draw call?

thanks for taking time to answer us, this thread is very valuable.

It’s only for usage inside an invalidation panel, outside an invalidation panel all widgets are effectively volatile, since we redraw them / recalculate everything every frame. Yes, just a property on widgets.

Correct. Similar (from the shader’s point of view) widgets can be bucketed together and their geometry sent down together in a single draw call, instead of 1 draw call per widget.