Browse Source

Profiler:

- added new data columns
- added hot path indicator if method takes more than 20% time of the parent node

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4873 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 16 years ago
parent
commit
9dbff240b9
  1. 16
      src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs
  2. 2
      src/AddIns/Misc/Profiler/Controller/Data/PerformanceCounterDescriptor.cs
  3. 2
      src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
  4. 28
      src/AddIns/Misc/Profiler/Controller/Data/UnitTestRootCallTreeNode.cs
  5. 2
      src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/ProfilerView.xaml
  6. 42
      src/AddIns/Misc/Profiler/Frontend/Controls/CallTreeNodeViewModel.cs
  7. 2
      src/AddIns/Misc/Profiler/Frontend/Controls/Controls.csproj
  8. 22
      src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml
  9. 11
      src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml.cs

16
src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs

@ -66,10 +66,24 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -66,10 +66,24 @@ namespace ICSharpCode.Profiler.Controller.Data
public abstract bool IsActiveAtStart { get; }
/// <summary>
/// Gets how many CPU cycles where spent inside this method, including sub calls.
/// Gets how many CPU cycles were spent inside this method, including sub calls.
/// </summary>
public abstract long CpuCyclesSpent { get; }
/// <summary>
/// Gets how many CPU cycles were spent inside this method, excluding sub calls.
/// </summary>
public virtual long CpuCyclesSpentSelf {
get {
return GetCpuCyclesSelf();
}
}
long GetCpuCyclesSelf()
{
return CpuCyclesSpent - Children.Aggregate(0L, (sum, item) => sum + item.CpuCyclesSpent);
}
/// <summary>
/// Gets the name of the method including namespace and class name.
/// </summary>

2
src/AddIns/Misc/Profiler/Controller/Data/PerformanceCounterDescriptor.cs

@ -11,8 +11,6 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -11,8 +11,6 @@ namespace ICSharpCode.Profiler.Controller.Data
{
public class PerformanceCounterDescriptor
{
public PerformanceCounterDescriptor()
{
}

2
src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs

@ -350,7 +350,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -350,7 +350,7 @@ namespace ICSharpCode.Profiler.Controller.Data
/// <inheritdoc/>
public override IQueryable<CallTreeNode> GetFunctions(int startIndex, int endIndex)
{
if (startIndex < 0 || startIndex > endIndex)
if (startIndex < 0 || startIndex >= this.dataSets.Count)
throw new ArgumentOutOfRangeException("startIndex", startIndex, "Value must be between 0 and " + endIndex);
if (endIndex < startIndex || endIndex >= this.DataSets.Count)
throw new ArgumentOutOfRangeException("endIndex", endIndex, "Value must be between " + startIndex + " and " + (this.DataSets.Count - 1));

28
src/AddIns/Misc/Profiler/Controller/Data/UnitTestRootCallTreeNode.cs

@ -25,67 +25,75 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -25,67 +25,75 @@ namespace ICSharpCode.Profiler.Controller.Data
this.unitTests = new List<CallTreeNode>(unitTests);
}
/// <summary>
/// Gets a reference to the name, return type and parameter list of the method.
/// </summary>
/// <inheritdoc/>
public override NameMapping NameMapping {
get {
return new NameMapping(0, null, "Merged node", null);
}
}
/// <inheritdoc/>
public override long CpuCyclesSpent {
get {
return 0;
}
}
/// <inheritdoc/>
public override bool IsActiveAtStart {
get {
return this.unitTests.Any(test => test.IsActiveAtStart);
}
}
/// <inheritdoc/>
public override double TimeSpent {
get {
return 0;
}
}
/// <inheritdoc/>
public override int RawCallCount {
get {
return 0;
}
}
/// <inheritdoc/>
public override CallTreeNode Parent {
get {
return null;
}
}
/// <inheritdoc/>
public override CallTreeNode Merge(System.Collections.Generic.IEnumerable<CallTreeNode> nodes)
{
// throw new ShouldNeverHappenException();
throw new NotSupportedException("Cannot merge a UnitTestRootCallTreeNode (should never be possible)");
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.unitTests.Aggregate(0, (sum, item) => sum ^= item.GetHashCode());
}
/// <inheritdoc/>
public override bool Equals(CallTreeNode other)
{
return (other is UnitTestRootCallTreeNode) && (other as UnitTestRootCallTreeNode).unitTests.SequenceEqual(unitTests);
}
/// <inheritdoc/>
public override IQueryable<CallTreeNode> Callers {
get {
return Enumerable.Empty<CallTreeNode>().AsQueryable();
}
}
/// <inheritdoc/>
public override IQueryable<CallTreeNode> Children {
get {
return unitTests.AsQueryable();

2
src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/ProfilerView.xaml

@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
<y:QueryView x:Name="treeView" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ShowQueryItems="False" CurrentQuery="from t in Threads select t" IsQueryModifiable="False" />
</TabItem>
<TabItem Header="Top 20">
<y:QueryView x:Name="top20View" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ShowQueryItems="False" CurrentQuery="(from f in Functions where f.CallCount > 0 orderby f.CpuCyclesSpent descending select f).Take(20)" IsQueryModifiable="False" />
<y:QueryView x:Name="top20View" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ShowQueryItems="False" CurrentQuery="(from f in Functions where f.CallCount > 0 orderby f.CpuCyclesSpentSelf descending select f).Take(20)" IsQueryModifiable="False" />
</TabItem>
<TabItem Name="dummyTab" Header="">
</TabItem>

42
src/AddIns/Misc/Profiler/Frontend/Controls/CallTreeNodeViewModel.cs

@ -46,7 +46,7 @@ namespace ICSharpCode.Profiler.Controls @@ -46,7 +46,7 @@ namespace ICSharpCode.Profiler.Controls
public event EventHandler<NodeEventArgs<CallTreeNodeViewModel>> RequestBringIntoView;
protected virtual void OnRequestBringIntoView(NodeEventArgs<CallTreeNodeViewModel> e)
{
{
if (RequestBringIntoView != null) {
RequestBringIntoView(this, e);
}
@ -101,6 +101,15 @@ namespace ICSharpCode.Profiler.Controls @@ -101,6 +101,15 @@ namespace ICSharpCode.Profiler.Controls
}
}
public Visibility HotPathIndicatorVisibility {
get {
if (TimePercentageOfParent >= 0.2)
return Visibility.Visible;
return Visibility.Collapsed;
}
}
CallTreeNodeViewModel GetNodeFromLevel(int level)
{
if (this.level > level) {
@ -258,7 +267,7 @@ namespace ICSharpCode.Profiler.Controls @@ -258,7 +267,7 @@ namespace ICSharpCode.Profiler.Controls
OnPropertyChanged("IsExpanded");
this.IsExpandedChanged(new NodeEventArgs<CallTreeNodeViewModel>(this));
if (!isExpanded) {
if (isExpanded) {
DeselectChildren(children);
}
}
@ -328,6 +337,35 @@ namespace ICSharpCode.Profiler.Controls @@ -328,6 +337,35 @@ namespace ICSharpCode.Profiler.Controls
}
}
public string TimeSpentSelf {
get {
if (!node.IsThread) {
double value = node.TimeSpent - node.Children.Aggregate(0.0, (sum, item) => sum + item.TimeSpent);
return value.ToString("f6") + "ms";
} else
return null;
}
}
public string TimeSpentSelfPerCall {
get {
if (!node.IsThread) {
double value = node.TimeSpent - node.Children.Aggregate(0.0, (sum, item) => sum + item.TimeSpent);
return (value / node.CallCount).ToString("f6") + "ms";
} else
return null;
}
}
public string TimeSpentPerCall {
get {
if (!node.IsThread)
return (node.TimeSpent / node.CallCount).ToString("f6") + "ms";
else
return null;
}
}
public string CallCount {
get {
if (!node.IsThread)

2
src/AddIns/Misc/Profiler/Frontend/Controls/Controls.csproj

@ -93,6 +93,8 @@ @@ -93,6 +93,8 @@
<Page Include="ExtendedTimeLineControl.xaml" />
<Page Include="QueryView.xaml" />
<Page Include="Themes\Generic.xaml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Controller\Controller.csproj">
<Project>{72FFB35A-C9E2-4A31-B4FA-E3E3E28DED5F}</Project>
<Name>Controller</Name>

22
src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml

@ -77,6 +77,7 @@ @@ -77,6 +77,7 @@
<local:CustomGridViewScrollableCell CurrentScrollPosition="{Binding ElementName=treeView, Path=View.CurrentScrollPosition}">
<StackPanel Orientation="Horizontal">
<ToggleButton Visibility="{Binding CheckBoxVisibility}" IsChecked="{Binding IsExpanded}" Margin="{Binding IndentationMargin}" Style="{StaticResource ExpandCollapseToggleStyle}" />
<Ellipse Width="10" Height="10" HorizontalAlignment="Center" Margin="0,0,0,3" Fill="Red" Visibility="{Binding HotPathIndicatorVisibility}" />
<TextBlock Text="{Binding Name}" ToolTip="{Binding ToolTip}" />
</StackPanel>
</local:CustomGridViewScrollableCell>
@ -97,6 +98,27 @@ @@ -97,6 +98,27 @@
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Time spent (self)" Width="110" x:Name="timeSpentSelfColumn">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Right" Text="{Binding TimeSpentSelf}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Time spent/call" Width="110" x:Name="timeSpentPerCallColumn">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Right" Text="{Binding TimeSpentPerCall}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Time spent (self)/call" Width="110" x:Name="timeSpentSelfPerCallColumn">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Right" Text="{Binding TimeSpentSelfPerCall}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="%" Width="80" x:Name="percentColumn">
<GridViewColumn.CellTemplate>
<DataTemplate>

11
src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml.cs

@ -86,8 +86,6 @@ namespace ICSharpCode.Profiler.Controls @@ -86,8 +86,6 @@ namespace ICSharpCode.Profiler.Controls
ad.Child = bar;
layer.Add(ad);
CallTreeNode resultRoot;
searchTask.Execute(
() => DoSearchInBackground(list.Roots.Select(i => i.Node).ToList(), start, end, text, true),
result => SearchCompleted(result, layer, ad),
@ -160,9 +158,12 @@ namespace ICSharpCode.Profiler.Controls @@ -160,9 +158,12 @@ namespace ICSharpCode.Profiler.Controls
this.treeView.SizeChanged += delegate(object sender, SizeChangedEventArgs e) {
if (e.NewSize.Width > 0 && e.PreviousSize.Width > 0 &&
(nameColumn.Width + (e.NewSize.Width - e.PreviousSize.Width)) > 0) {
if ((nameColumn.Width + (e.NewSize.Width - e.PreviousSize.Width)) >=
(e.NewSize.Width - this.callCountColumn.Width - this.percentColumn.Width - this.timeSpentColumn.Width))
this.nameColumn.Width = e.NewSize.Width - this.callCountColumn.Width - this.percentColumn.Width - this.timeSpentColumn.Width - 25;
double newValue = e.NewSize.Width - this.callCountColumn.Width
- this.percentColumn.Width - this.timeSpentColumn.Width
- this.timeSpentSelfColumn.Width - this.timeSpentPerCallColumn.Width
- this.timeSpentSelfPerCallColumn.Width;
if ((nameColumn.Width + (e.NewSize.Width - e.PreviousSize.Width)) >= newValue)
this.nameColumn.Width = newValue - 25;
else
nameColumn.Width += (e.NewSize.Width - e.PreviousSize.Width);
}

Loading…
Cancel
Save