Page 1 of 1

Performance hit from simple binding

Posted: 18 Jun 2019, 14:41
by asusralis
I have a DateTime that I'm updating every frame, and it's surprisingly taking a lot of cpu time.

Where it's updated:
        private void UpdateTime()
        {
            DeltaTime = TimeSpan.FromMinutes(Time.deltaTime * 4);

            _game.Player.Time += DeltaTime;
        }
                        <TextBlock FontSize="30" Foreground="White" VerticalAlignment="Center" Margin="5"
                           Text="{Binding Game.Player.Time, Converter={StaticResource DateTimeFormat}, ConverterParameter=HH:mm}"/>
                        <Rectangle Width="1" Fill="White" Margin="5, 10"/>
                        <TextBlock FontSize="30" Foreground="White" VerticalAlignment="Center" Margin="5"
                           Text="{Binding Game.Player.Time.Day,StringFormat=Day: {0}}"/>
public class DateTimeFormatConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ((DateTime)value).ToString(parameter.ToString());
        }

        public object ConvertBack(object value, Type targetType, object parameter,
            CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
Profiler:
https://i.imgur.com/oVSpgiY.png
https://i.imgur.com/T71v9KG.png
Sometimes it gets really bad:
https://i.imgur.com/YOBk5LC.png

I'm using a converter because I couldn't get the DateTime to display in a specific format without it (like how it works in WPF). I've also set many binded properties every frame before without any performance hits.

I'm on Unity 2019.1.5 / Noesis 2.2.3

EDIT: there seems to be a memory leak: https://i.imgur.com/yhfXiBe.png

Re: Performance hit from simple binding

Posted: 19 Jun 2019, 19:12
by sfernandez
Without a deep analysis it seems a problem with lots of boxing objects being created.
Could you do a fast test exposing in the Player directly the strings you want in the UI, something like:
class Player
{
  ...
  public string TimeHour { get { return Time.ToString("HH:mm"); } }
  public string TimeDay { get { return Time.Day.ToString(); } }
  //  when Time property changes you'll need to notify of changes in these properties also
}
<TextBlock FontSize="30" Foreground="White" VerticalAlignment="Center" Margin="5"
    Text="{Binding Game.Player.TimeHour}"/>
<Rectangle Width="1" Fill="White" Margin="5, 10"/>
<TextBlock FontSize="30" Foreground="White" VerticalAlignment="Center" Margin="5"
    Text="{Binding Game.Player.TimeDay}"/>
Anyway, this is something we need to carefully investigate because those numbers are horrible, I created a ticket in our bugtracker to follow it: https://www.noesisengine.com/bugs/view.php?id=1498

Re: Performance hit from simple binding

Posted: 19 Jun 2019, 21:37
by asusralis
It fixed it - when changing to what you suggested, it now takes .21ms: https://i.imgur.com/yZ7Sh1D.png

Is there something wrong with the converter I wrote?

Re: Performance hit from simple binding

Posted: 20 Jun 2019, 13:12
by sfernandez
Nothing wrong on your approach, it is more a problem on how we deal with struct instances and it is something we will have to fix.

Re: Performance hit from simple binding

Posted: 20 Jun 2019, 17:41
by asusralis
Would this have also caused the memory leak?And if I'm binding to structures, try to avoid converters for now?

Lastly, is there a reason why something like this doesn't work with DateTime in Noesis: StringFormat='{}{0:dd/MM/yyyy}' ? I could not get any of the DateTime formats to work like this.

Re: Performance hit from simple binding

Posted: 21 Jun 2019, 16:56
by sfernandez
Would this have also caused the memory leak?
That memory was probably just kept until the Garbage Collector decided to free it, because those boxed objects shouldn't be referenced by anyone.
And if I'm binding to structures, try to avoid converters for now?
The problem is related to the binding of structure properties itslef when those structures are changing, not using a converter.
Lastly, is there a reason why something like this doesn't work with DateTime in Noesis: StringFormat='{}{0:dd/MM/yyyy}' ? I could not get any of the DateTime formats to work like this.
DateTime struct is not natively supported by Noesis as it occurs in WPF and C#, so right now it behaves like any custom class. I created a ticket for this feature: https://www.noesisengine.com/bugs/view.php?id=1504