Skip to content

Commit

Permalink
Added functionality for multiple profiling threads.
Browse files Browse the repository at this point in the history
Fixed several minor issues with performance and stability.
  • Loading branch information
bombomby committed May 20, 2015
1 parent 9bea418 commit 5cade26
Show file tree
Hide file tree
Showing 23 changed files with 393 additions and 131 deletions.
56 changes: 47 additions & 9 deletions Brofiler/Data/EventData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,8 @@ public String FullName
set
{
fullName = value;
name = fullName;

int lastNameSymbol = fullName.IndexOf('(');
if (lastNameSymbol != -1)
{
String leftPart = fullName.Substring(0, lastNameSymbol);
int startIndex = leftPart.LastIndexOf(' ');
name = leftPart.Substring(startIndex + 1);
}
name = StripFunctionArguments(fullName);
name = StripReturnValue(name);
}
}

Expand All @@ -58,5 +51,50 @@ public FileLine Path {
get { return path; }
set { path = value != null ? value : FileLine.Empty; }
}

static char startBracket = '(';
static char endBracket = ')';
static char[] brackets = new char[] { startBracket, endBracket };
static String StripFunctionArguments(String name)
{
int counter = 0;

int index = name.Length - 1;

while (index > 0)
{
index = name.LastIndexOfAny(brackets, index);
if (index != -1)
{
counter = counter + (name[index] == endBracket ? 1 : -1);
if (counter == 0)
return name.Substring(0, index);

--index;
}
}

return name;
}

static String[] callConventions = { "__thiscall", "__fastcall", "__cdecl", "__clrcall", "__stdcall", "__vectorcall" };
static String StripReturnValue(String name)
{
if (name.Length == 0)
return name;

foreach (String functionCall in callConventions)
{
int index = name.IndexOf(functionCall);
if (index != -1)
{
int cutIndex = index + functionCall.Length + 1;
if (cutIndex < name.Length)
return name.Substring(cutIndex);
}
}

return name;
}
}
}
25 changes: 24 additions & 1 deletion Brofiler/Message/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Profiler
{
public struct NetworkProtocol
{
public const UInt32 NETWORK_PROTOCOL_VERSION = 2;
public const UInt32 NETWORK_PROTOCOL_VERSION = 3;
}

public class DataResponse
Expand All @@ -21,6 +21,7 @@ public enum Type
SamplingFrame,
NullFrame,
ReportProgress,
Handshake
}

public Type ResponseType { get; set; }
Expand Down Expand Up @@ -93,6 +94,7 @@ public enum MessageType
Stop,
TurnSampling,
SetupHook,
SetupWorkingThread,
}

public abstract class Message
Expand Down Expand Up @@ -177,4 +179,25 @@ public override void Write(BinaryWriter writer)
}
}

class SetupWorkingThreadMessage : Message
{
UInt32 threadID;

public SetupWorkingThreadMessage(UInt32 threadID)
{
this.threadID = threadID;
}

public override Int32 GetMessageType()
{
return (Int32)MessageType.SetupWorkingThread;
}

public override void Write(BinaryWriter writer)
{
base.Write(writer);
writer.Write(threadID);
}
}

}
1 change: 0 additions & 1 deletion Brofiler/ProfilerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ public bool SendMessage(Message message)
lock (criticalSection)
{
//client.Client.Shutdown(SocketShutdown.Both);
client.Client.Disconnect(true);
client = new TcpClient();
}
}
Expand Down
2 changes: 1 addition & 1 deletion Brofiler/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.2.0")]
[assembly: AssemblyVersion("1.0.3.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
24 changes: 14 additions & 10 deletions Brofiler/TimeLine/TimeLine.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
xmlns:local="clr-namespace:Profiler"
xmlns:Profiler_Data="clr-namespace:Profiler.Data"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
x:Class="Profiler.TimeLine"
x:Name="UserControl" d:DesignWidth="822"
Expand All @@ -23,6 +24,7 @@
</Setter>
</Style>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<local:FrameHeightConverter x:Key="FrameHeightConverter"/>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
Expand All @@ -35,7 +37,7 @@
</ItemsPanelTemplate>
<DataTemplate x:Key="TimeLineItemTemplate">
<Grid x:Name="rect" Background="#02FFFFFF" Height="163" Width="14" Margin="-1,0,0,0" >
<local:TimeLineItem x:Name="timeLineItem" Height="{Binding Duration, Mode=OneTime}" Width="Auto" VerticalAlignment="Bottom" />
<local:TimeLineItem x:Name="timeLineItem" Height="{Binding Duration, Converter={StaticResource FrameHeightConverter}}" Width="Auto" VerticalAlignment="Bottom" />
<Label x:Name="frameDescriptionText" Content="{Binding Description, Mode=OneTime}" Width="Auto" VerticalAlignment="Bottom" Height="Auto" FontSize="12" Padding="0,0,0,0" Margin="-1,0,0,3" SnapsToDevicePixels="True" FontWeight="Bold" Grid.ColumnSpan="2" >
<Label.LayoutTransform>
<TransformGroup>
Expand All @@ -48,7 +50,7 @@
</Label>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="true">
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}, Mode=FindAncestor}}" Value="true">
<Setter TargetName="timeLineItem" Property="BorderThickness" Value="2" />
</DataTrigger>
</DataTemplate.Triggers>
Expand Down Expand Up @@ -107,7 +109,7 @@
</Grid.ColumnDefinitions>
<ListBox x:Name="frameList" ItemsPanel="{DynamicResource TimeLaneLayoutTemplate}" ItemTemplate="{DynamicResource TimeLineItemTemplate}" ItemsSource="{Binding Mode=OneWay}" DataContext="{Binding Mode=OneWay}" SelectionChanged="frameList_SelectionChanged" Background="White" Grid.Row="1" Margin="0,2,0,0" d:LayoutOverrides="Width" TextOptions.TextFormattingMode="Display">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
Expand All @@ -118,13 +120,13 @@
<StackPanel Orientation="Horizontal" Margin="0" Grid.ColumnSpan="2" HorizontalAlignment="Left">
<ToggleButton x:Name="StartButton" Content="ToggleButton" Width="24" Height="24" Unchecked="StartButton_Unchecked" Checked="StartButton_Checked" ToolTip="Start Profiling Session">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style TargetType="{x:Type ToggleButton}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="ContentTemplate" Value="{StaticResource StartButtonTemplate}" />
<Setter Property="ContentTemplate" Value="{StaticResource StartButtonTemplate}" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource StopButtonTemplate}" />
<Setter Property="ContentTemplate" Value="{StaticResource StopButtonTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
Expand All @@ -139,11 +141,13 @@
<TextBox x:Name="serverIP" Margin="5,0,0,0" Text="127.0.0.1" VerticalAlignment="Center" MaxLength="15" MaxLines="1" Width="100" TextChanged="serverIP_TextChanged" />
<Label Content="Port:" Margin="4,0,0,0" Padding="1" VerticalAlignment="Center"/>
<TextBox x:Name="serverPort" Margin="5,0,0,0" Width="45" Text="31313" VerticalAlignment="Center" MaxLines="1" TextChanged="serverPort_TextChanged" />
<Label Content="Frame:" Margin="4,0,0,0" Padding="1" VerticalAlignment="Center"/>
<TextBox x:Name="frameNumber" Margin="5,0,0,0" Width="45" Text="{Binding SelectedIndex, ElementName=frameList, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" VerticalAlignment="Center" MaxLines="1" TextChanged="serverPort_TextChanged" KeyDown="frameNumber_KeyDown" />
<StackPanel x:Name="warningBlock" Orientation="Horizontal">
<StackPanel x:Name="ActiveThreadPanel" Margin="0,3,0,3.02" Orientation="Horizontal">
<Label Content="Thread:" Padding="1" VerticalAlignment="Center"/>
<ComboBox x:Name="threadSelection" Margin="0" MinWidth="100" VerticalAlignment="Center" SelectionChanged="threadSelection_SelectionChanged" />
</StackPanel>
<StackPanel x:Name="warningBlock" Orientation="Horizontal">
<Image x:Name="warningIcon" Source="Icons/Warning-icon.png" Margin="5,0,0,0" Width="24" Height="24" />
<TextBlock VerticalAlignment="Center"><Hyperlink x:Name="warningUrl" RequestNavigate="Hyperlink_RequestNavigate"><Run x:Name="warningText">ClickMe</Run></Hyperlink></TextBlock>
<TextBlock VerticalAlignment="Center"><Hyperlink x:Name="warningUrl" RequestNavigate="Hyperlink_RequestNavigate"><Run x:Name="warningText" Text="ClickMe"/></Hyperlink></TextBlock>
</StackPanel>
</StackPanel>
<TextBlock x:Name="StatusText" TextWrapping="Wrap" Text="Capturing Frame 34" FontSize="20" TextAlignment="Center" Margin="0,2,0,0" Grid.Row="1" FontStyle="Italic" TextDecorations="{x:Null}" TextOptions.TextHintingMode="Animated" FontWeight="SemiBold" Foreground="Black" Visibility="Collapsed">
Expand Down
81 changes: 68 additions & 13 deletions Brofiler/TimeLine/TimeLine.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public TimeLine()
this.DataContext = frames;

warningBlock.Visibility = Visibility.Collapsed;

ActiveThreads = new ObservableCollection<ThreadDescription>();
threadSelection.ItemsSource = ActiveThreads;

ActiveThreadPanel.Visibility = System.Windows.Visibility.Collapsed;

this.Loaded += new RoutedEventHandler(TimeLine_Loaded);
}
Expand Down Expand Up @@ -191,6 +196,18 @@ private void SaveTestResponse(DataResponse response)
}
}

public class ThreadDescription
{
public UInt32 ThreadID { get; set; }
public String Name { get; set; }

public override string ToString()
{
return String.Format("[{0}] {1}", ThreadID, Name);
}
}
public ObservableCollection<ThreadDescription> ActiveThreads { get; set; }

private bool ApplyResponse(DataResponse response)
{
if (response.Version == NetworkProtocol.NETWORK_PROTOCOL_VERSION)
Expand All @@ -216,12 +233,31 @@ private bool ApplyResponse(DataResponse response)
}
break;

case DataResponse.Type.Handshake:
ActiveThreads.Clear();

UInt32 mainThreadID = response.Reader.ReadUInt32();
int count = response.Reader.ReadInt32();

for (int i = 0; i < count; ++i)
{
UInt32 threadID = response.Reader.ReadUInt32();
String name = new String(response.Reader.ReadChars(response.Reader.ReadInt32()));
ActiveThreads.Add(new ThreadDescription() { Name = name, ThreadID = threadID });

if (threadID == mainThreadID)
threadSelection.SelectedIndex = i;
}

ActiveThreadPanel.Visibility = System.Windows.Visibility.Visible;
break;

default:
StatusText.Visibility = System.Windows.Visibility.Collapsed;
lock (frames)
{
frames.Add(response.ResponseType, response.Reader);
ScrollToEnd();
//ScrollToEnd();
}
break;
}
Expand Down Expand Up @@ -251,7 +287,7 @@ public void RecieveMessage()
if (response != null)
Application.Current.Dispatcher.Invoke(new Action(() => ApplyResponse(response)));
else
Thread.Sleep(100);
Thread.Sleep(1000);
}
}

Expand Down Expand Up @@ -310,8 +346,9 @@ public void Close()

private void serverIP_TextChanged(object sender, TextChangedEventArgs e)
{
IPAddress ip = IPAddress.Parse(serverIP.Text);
if (ip != null)
IPAddress ip = null;

if (IPAddress.TryParse(serverIP.Text, out ip))
ProfilerClient.Get().IpAddress = ip;
}

Expand Down Expand Up @@ -383,15 +420,6 @@ private void ClearHooksButton_Click(object sender, System.Windows.RoutedEventArg
ProfilerClient.Get().SendMessage(new SetupHookMessage(0, false));
}

private void frameNumber_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TraversalRequest down = new TraversalRequest(FocusNavigationDirection.Down);
frameNumber.MoveFocus(down);
}
}

private void StartButton_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
ProfilerClient.Get().SendMessage(new StopMessage());
Expand All @@ -416,5 +444,32 @@ private void StartButton_Checked(object sender, System.Windows.RoutedEventArgs e
}
}
}

private void threadSelection_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (threadSelection.SelectedItem is ThreadDescription)
{
ThreadDescription desc = threadSelection.SelectedItem as ThreadDescription;
ProfilerClient.Get().SendMessage(new SetupWorkingThreadMessage(desc.ThreadID));
}
}
}

public class FrameHeightConverter : IValueConverter
{
public static double Convert(double value)
{
return 2.0 * value;
}

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Convert((double)value);
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
}
3 changes: 2 additions & 1 deletion Brofiler/TimeLine/TimeLineItem.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ void Init()
Data.EventFrame frame = (Data.EventFrame)DataContext;
LayoutRoot.Children.Clear();


foreach (var entry in frame.Categories)
{
Rectangle rect = new Rectangle();
rect.Width = Double.NaN;
rect.Height = entry.Duration;
rect.Height = FrameHeightConverter.Convert(entry.Duration);
rect.Fill = new SolidColorBrush(entry.Description.Color);
LayoutRoot.Children.Add(rect);
}
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2015 bombomby
Copyright (c) 2015 Vadim Slyusarev

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit 5cade26

Please sign in to comment.