Plugins - Added profiling API

UI - Added profiling tab to debugger
This commit is contained in:
Robert committed 2021-05-16 20:22:13 +02:00
1 parent f13ab9852f
commit 4b24834fd6
18 files changed
+518 -18

No files matched your search

@@ -190,6 +190,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
ShowRepeatButton = SegmentWidth > 45 && IsMainSegment;
ShowDisableButton = SegmentWidth > 25;
if (Segment == SegmentViewModelType.Main)
NotifyOfPropertyChange(nameof(RepeatSegment));
}
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.Settings.Debug.Tabs;
using Artemis.UI.Screens.Settings.Debug.Tabs.Performance;
using Stylet;
namespace Artemis.UI.Screens.Settings.Debug
@@ -16,12 +16,14 @@ namespace Artemis.UI.Screens.Settings.Debug
ICoreService coreService,
RenderDebugViewModel renderDebugViewModel,
DataModelDebugViewModel dataModelDebugViewModel,
LogsDebugViewModel logsDebugViewModel)
LogsDebugViewModel logsDebugViewModel,
PerformanceDebugViewModel performanceDebugViewModel)
{
_coreService = coreService;
Items.Add(renderDebugViewModel);
Items.Add(dataModelDebugViewModel);
Items.Add(logsDebugViewModel);
Items.Add(performanceDebugViewModel);
ActiveItem = renderDebugViewModel;
StayOnTopSetting = settingsService.GetSetting("Debugger.StayOnTop", false);
@@ -0,0 +1,52 @@
using Artemis.Core;
using Stylet;
namespace Artemis.UI.Screens.Settings.Debug.Tabs.Performance
{
public class PerformanceDebugMeasurementViewModel : PropertyChangedBase
{
private string _average;
private string _last;
private string _max;
private string _min;
public PerformanceDebugMeasurementViewModel(ProfilingMeasurement measurement)
{
Measurement = measurement;
}
public ProfilingMeasurement Measurement { get; }
public string Last
{
get => _last;
set => SetAndNotify(ref _last, value);
}
public string Average
{
get => _average;
set => SetAndNotify(ref _average, value);
}
public string Min
{
get => _min;
set => SetAndNotify(ref _min, value);
}
public string Max
{
get => _max;
set => SetAndNotify(ref _max, value);
}
public void Update()
{
Last = Measurement.GetLast().TotalMilliseconds + " ms";
Average = Measurement.GetAverage().TotalMilliseconds + " ms";
Min = Measurement.GetMin().TotalMilliseconds + " ms";
Max = Measurement.GetMax().TotalMilliseconds + " ms";
}
}
}
@@ -0,0 +1,33 @@
<UserControl x:Class="Artemis.UI.Screens.Settings.Debug.Tabs.Performance.PerformanceDebugPluginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Debug.Tabs.Performance"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:PerformanceDebugPluginViewModel}">
<materialDesign:Card Margin="0 5" Padding="10">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<shared:ArtemisIcon Grid.Column="0" Icon="{Binding Icon}" Width="24" Height="24" />
<TextBlock Grid.Column="1" VerticalAlignment="Center" Style="{StaticResource MaterialDesignSubtitle1TextBlock}" Text="{Binding Plugin.Info.Name}" />
</Grid>
<ItemsControl ItemsSource="{Binding Profilers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</materialDesign:Card>
</UserControl>
@@ -0,0 +1,32 @@
using System.Linq;
using Artemis.Core;
using Artemis.UI.Shared;
using Stylet;
namespace Artemis.UI.Screens.Settings.Debug.Tabs.Performance
{
public class PerformanceDebugPluginViewModel : Screen
{
public Plugin Plugin { get; }
public object Icon { get; }
public PerformanceDebugPluginViewModel(Plugin plugin)
{
Plugin = plugin;
Icon = PluginUtilities.GetPluginIcon(Plugin, Plugin.Info.Icon);
}
public BindableCollection<PerformanceDebugProfilerViewModel> Profilers { get; } = new();
public void Update()
{
foreach (Profiler pluginProfiler in Plugin.Profilers.Where(p => p.Measurements.Any()))
{
if (Profilers.All(p => p.Profiler != pluginProfiler))
Profilers.Add(new PerformanceDebugProfilerViewModel(pluginProfiler));
}
foreach (PerformanceDebugProfilerViewModel profilerViewModel in Profilers)
profilerViewModel.Update();
}
}
}
@@ -0,0 +1,33 @@
<UserControl x:Class="Artemis.UI.Screens.Settings.Debug.Tabs.Performance.PerformanceDebugProfilerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Debug.Tabs.Performance"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:PerformanceDebugProfilerViewModel}">
<StackPanel>
<TextBlock Style="{StaticResource MaterialDesignBody2TextBlock}" Text="{Binding Profiler.Name}" Margin="10 10 0 0" />
<DataGrid ItemsSource="{Binding Measurements}"
d:DataContext="{d:DesignInstance Type={x:Type local:PerformanceDebugMeasurementViewModel}}"
CanUserSortColumns="True"
IsReadOnly="True"
CanUserAddRows="False"
AutoGenerateColumns="False"
materialDesign:DataGridAssist.CellPadding="16 5 5 5"
materialDesign:DataGridAssist.ColumnHeaderPadding="16 5 5 5"
CanUserResizeRows="False"
Margin="10 5 10 10">
<DataGrid.Columns>
<materialDesign:DataGridTextColumn Binding="{Binding Measurement.Identifier}" Header="Identifier" />
<materialDesign:DataGridTextColumn Binding="{Binding Last}" Header="Last" />
<materialDesign:DataGridTextColumn Binding="{Binding Min}" Header="Min" />
<materialDesign:DataGridTextColumn Binding="{Binding Max}" Header="Max" />
<materialDesign:DataGridTextColumn Binding="{Binding Average}" Header="Average" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</UserControl>
@@ -0,0 +1,30 @@
using System.Linq;
using Artemis.Core;
using Stylet;
namespace Artemis.UI.Screens.Settings.Debug.Tabs.Performance
{
public class PerformanceDebugProfilerViewModel : Screen
{
public Profiler Profiler { get; }
public PerformanceDebugProfilerViewModel(Profiler profiler)
{
Profiler = profiler;
}
public BindableCollection<PerformanceDebugMeasurementViewModel> Measurements { get; } = new();
public void Update()
{
foreach ((string _, ProfilingMeasurement measurement) in Profiler.Measurements)
{
if (Measurements.All(m => m.Measurement != measurement))
Measurements.Add(new PerformanceDebugMeasurementViewModel(measurement));
}
foreach (PerformanceDebugMeasurementViewModel profilingMeasurementViewModel in Measurements)
profilingMeasurementViewModel.Update();
}
}
}
@@ -0,0 +1,35 @@
<UserControl x:Class="Artemis.UI.Screens.Settings.Debug.Tabs.Performance.PerformanceDebugView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Debug.Tabs.Performance"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:PerformanceDebugViewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" TextWrapping="Wrap">
In this window you can see how much CPU time different plugin features are taking.
If you are having performance issues, below you can find out which plugin might be the culprit.
</TextBlock>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
<ItemsControl ItemsSource="{Binding Items}" Margin="0 0 10 0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<materialDesign:TransitioningContent OpeningEffect="{materialDesign:TransitionEffect SlideInFromLeft}"
OpeningEffectsOffset="{materialDesign:IndexedItemOffsetMultiplier 0:0:0.05}">
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</materialDesign:TransitioningContent>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
@@ -0,0 +1,77 @@
using System.Linq;
using System.Timers;
using Artemis.Core;
using Artemis.Core.Services;
using Stylet;
namespace Artemis.UI.Screens.Settings.Debug.Tabs.Performance
{
public class PerformanceDebugViewModel : Conductor<PerformanceDebugPluginViewModel>.Collection.AllActive
{
private readonly IPluginManagementService _pluginManagementService;
private readonly Timer _updateTimer;
public PerformanceDebugViewModel(IPluginManagementService pluginManagementService)
{
_pluginManagementService = pluginManagementService;
_updateTimer = new Timer(500);
DisplayName = "PERFORMANCE";
_updateTimer.Elapsed += UpdateTimerOnElapsed;
}
private void UpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
{
foreach (PerformanceDebugPluginViewModel viewModel in Items)
viewModel.Update();
}
private void FeatureToggled(object? sender, PluginFeatureEventArgs e)
{
Items.Clear();
PopulateItems();
}
private void PluginToggled(object? sender, PluginEventArgs e)
{
Items.Clear();
PopulateItems();
}
private void PopulateItems()
{
Items.AddRange(_pluginManagementService.GetAllPlugins()
.Where(p => p.IsEnabled && p.Profilers.Any(pr => pr.Measurements.Any()))
.OrderBy(p => p.Info.Name)
.Select(p => new PerformanceDebugPluginViewModel(p)));
}
#region Overrides of Screen
/// <inheritdoc />
protected override void OnActivate()
{
PopulateItems();
_updateTimer.Start();
_pluginManagementService.PluginDisabled += PluginToggled;
_pluginManagementService.PluginDisabled += PluginToggled;
_pluginManagementService.PluginFeatureEnabled += FeatureToggled;
_pluginManagementService.PluginFeatureDisabled += FeatureToggled;
base.OnActivate();
}
/// <inheritdoc />
protected override void OnDeactivate()
{
_updateTimer.Stop();
_pluginManagementService.PluginDisabled -= PluginToggled;
_pluginManagementService.PluginDisabled -= PluginToggled;
_pluginManagementService.PluginFeatureEnabled -= FeatureToggled;
_pluginManagementService.PluginFeatureDisabled -= FeatureToggled;
Items.Clear();
base.OnDeactivate();
}
#endregion
}
}