Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Krüger <mkrueger@novell.com>2010-11-22 10:28:54 +0300
committerMike Krüger <mkrueger@novell.com>2010-11-22 10:28:54 +0300
commitfe512447d739b804ff781bac5dfd13ade750ca61 (patch)
tree9c9af6800f8ae5565a4f0c62a90a1f967325bca3 /main/src/addins/MonoDevelop.ProfilerGui
parentdd3b3f7e852d0ddbdcc0e516e572a57bc244f44b (diff)
Renamed directoryj
Diffstat (limited to 'main/src/addins/MonoDevelop.ProfilerGui')
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfileDialog.cs487
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionHandler.cs114
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionModeSet.cs50
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeCellRenderer.cs76
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeLineWidget.cs182
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.addin.xml28
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.csproj104
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.sln20
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Header.cs67
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/LogBuffer.cs57
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Util.cs79
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/MonoDevelop.Profiler.ProfileDialog.cs79
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/generated.cs29
-rw-r--r--main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/gui.stetic96
14 files changed, 1468 insertions, 0 deletions
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfileDialog.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfileDialog.cs
new file mode 100644
index 0000000000..229aa5ba78
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfileDialog.cs
@@ -0,0 +1,487 @@
+//
+// ProfileDialog.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Gtk;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Profiler
+{
+ public partial class ProfileDialog : Gtk.Window
+ {
+ const int MethodInfoColumn = 4;
+
+ TimeLineWidget timeLineWidget;
+ TreeStore store;
+ ListStore threadStore;
+ LogBuffer buffer;
+ uint timeout;
+
+ protected override void OnDestroyed ()
+ {
+ if (timeout != 0) {
+ GLib.Source.Remove (timeout);
+ timeout = 0;
+ }
+ base.OnDestroyed ();
+ }
+
+ public ProfileDialog (string fileName) : base(Gtk.WindowType.Toplevel)
+ {
+ this.Build ();
+ timeLineWidget = new TimeLineWidget (this);
+ scrolledwindow1.AddWithViewport (timeLineWidget);
+ scrolledwindow1.ShowAll ();
+
+ threadStore = new ListStore (typeof(string), typeof(AnalyseVisitor.ThreadContext));
+ comboboxThreads.Model = threadStore;
+ comboboxThreads.Changed += HandleComboboxThreadsChanged;
+ store = new TreeStore (typeof(string), // name
+ typeof(string), // icon
+ typeof(ulong), // call count
+ typeof(double), // time with children
+ typeof(AnalyseVisitor.MethodInfo) // method info
+ );
+ profileResultsView.Model = store;
+
+ var methodColumn = new TreeViewColumn ();
+ methodColumn.SortColumnId = 0;
+ methodColumn.SortIndicator = true;
+ methodColumn.Title = "Method";
+ methodColumn.Resizable = true;
+
+ var textRender = new CellRendererText ();
+ methodColumn.PackStart (textRender, true);
+ methodColumn.AddAttribute (textRender, "text", 0);
+ profileResultsView.AppendColumn (methodColumn);
+
+ var timeWithChidrenColumn = new TreeViewColumn ();
+ timeWithChidrenColumn.SortColumnId = 3;
+ timeWithChidrenColumn.SortIndicator = true;
+ timeWithChidrenColumn.Title = "Time with children (%)";
+ timeWithChidrenColumn.Resizable = true;
+ var timeCellRenderer = new TimeCellRenderer ();
+ timeWithChidrenColumn.PackStart (timeCellRenderer, true);
+ timeWithChidrenColumn.AddAttribute (timeCellRenderer, "time", 3);
+ profileResultsView.AppendColumn (timeWithChidrenColumn);
+
+ var callCountColumn = new TreeViewColumn ();
+ callCountColumn.SortIndicator = true;
+ callCountColumn.SortColumnId = 2;
+ callCountColumn.Resizable = true;
+ callCountColumn.Title = "Call count";
+ callCountColumn.PackStart (textRender, true);
+ callCountColumn.SetCellDataFunc (textRender, delegate (Gtk.TreeViewColumn column, Gtk.CellRenderer cell,Gtk.TreeModel model, Gtk.TreeIter iter) {
+ ulong callCount = (ulong)model.GetValue (iter, 2);
+ ((CellRendererText)cell).Text = callCount.ToString ();
+ });
+
+ profileResultsView.AppendColumn (callCountColumn);
+ profileResultsView.TestExpandRow += HandleProfileResultsViewTestExpandRow;
+ profileResultsView.ShowExpanders = true;
+
+// timeout = GLib.Timeout.Add (500, delegate {
+ try {
+ buffer = LogBuffer.Read (fileName);
+ } catch (Exception) {
+ }
+ AnalyzeBuffer ();
+/* return true;
+ });*/
+ }
+
+
+ long SelectedThreadID {
+ get {
+ if (comboboxThreads.Active > 0) {
+ TreeIter iter;
+ if (threadStore.GetIterFromString (out iter, comboboxThreads.Active.ToString ())) {
+ var thread = (AnalyseVisitor.ThreadContext)threadStore.GetValue (iter, 1);
+ return thread.ThreadId;
+ }
+ }
+ return 0L;
+ }
+ }
+
+ void HandleComboboxThreadsChanged (object sender, EventArgs e)
+ {
+ visitor.LookupThread = SelectedThreadID;
+ AnalyzeBuffer ();
+ }
+
+ internal AnalyseVisitor visitor = new AnalyseVisitor ();
+ HashSet<string> expandedRows = new HashSet<string> ();
+ void HandleProfileResultsViewTestExpandRow (object o, TestExpandRowArgs args)
+ {
+ string path = store.GetPath (args.Iter).ToString ();
+ if (expandedRows.Contains (path)) {
+ args.RetVal = false;
+ return;
+ }
+ expandedRows.Add (path);
+ var info = (AnalyseVisitor.MethodInfo)store.GetValue (args.Iter, MethodInfoColumn);
+ TreeIter child;
+ while (store.IterChildren (out child, args.Iter)) {
+ store.Remove (ref child);
+ }
+
+ foreach (var methodCall in info.CallStack) {
+ AppendMethodInfo (args.Iter, methodCall);
+ }
+ }
+
+ public void SetTime (ulong start, ulong end)
+ {
+ if (buffer == null)
+ return;
+ ulong t0 = buffer.buffers [0].Header.TimeBase;
+ visitor.StartTime = t0 + start;
+ visitor.EndTime = t0 + end;
+ System.Console.WriteLine ("set time:" + visitor.StartTime + " - " + visitor.EndTime);
+ AnalyzeBuffer ();
+ }
+
+ internal ulong totalTime = 0;
+ void AnalyzeBuffer ()
+ {
+ if (buffer == null)
+ return;
+ long selectedID = SelectedThreadID;
+ visitor.LookupThread = selectedID;
+ visitor.Reset ();
+ totalTime = 0;
+ foreach (var b in buffer.buffers) {
+ visitor.CurrentBuffer = b;
+ b.RunVisitor (visitor);
+ totalTime += visitor.TimeBase - b.Header.TimeBase;
+ }
+
+ comboboxThreads.Changed -= HandleComboboxThreadsChanged;
+ threadStore.Clear ();
+ threadStore.AppendValues ("[All Threads]", null);
+ bool first = true;
+ int active = 0;
+ int i = 1;
+ foreach (var thread in visitor.threadDictionary.Values) {
+ string name = thread.Name;
+ if (string.IsNullOrEmpty (name) && first) {
+ name = "GUI Thread";
+ }
+ first = false;
+ if (thread.ThreadId == selectedID)
+ active = i;
+ threadStore.AppendValues (name + " (" + thread.ThreadId + ")", thread);
+ i++;
+ }
+ comboboxThreads.Active = active;
+ comboboxThreads.Changed += HandleComboboxThreadsChanged;
+ store.Clear ();
+
+ foreach (var info in visitor.methodDictionary.Values) {
+ if (info.Calls == 0)
+ continue;
+ AppendMethodInfo (TreeIter.Zero, info);
+ }
+ }
+
+ void AppendMethodInfo (TreeIter iter, AnalyseVisitor.MethodInfo info)
+ {
+ TreeIter subiter;
+ double time = (double)totalTime;
+ if (visitor.StartTime != 0) {
+ time = (visitor.EndTime - visitor.StartTime);
+ System.Console.WriteLine (totalTime + ":" + time);
+ }
+ if (iter.Equals (TreeIter.Zero)) {
+ subiter = store.AppendValues (info.Name,
+ "",
+ info.Calls,
+ 100.0 * (double)info.TimeWithChildren / time,
+ info);
+ } else {
+ subiter = store.AppendValues (iter, info.Name,
+ "",
+ info.Calls,
+ 100.0 * (double)info.TimeWithChildren / time,
+ info);
+ }
+ if (info.CallStack.Count > 0) {
+ store.AppendValues (subiter, "",
+ "",
+ 0UL,
+ 0d,
+ null);
+ }
+
+ }
+
+ public class AnalyseVisitor : EventVisitor
+ {
+ Buffer currentBuffer;
+ ThreadContext currentThread;
+ long methodBase;
+ ulong timeBase;
+ ulong eventCount = 0;
+ ulong lastTimeBase = 0;
+ const int interval = 100000;
+ public List<ulong> Events = new List<ulong> ();
+ public ulong StartTime {
+ get;
+ set;
+ }
+
+ public ulong EndTime {
+ get;
+ set;
+ }
+
+ public ulong TimeBase {
+ get {
+ return timeBase;
+ }
+ set {
+ eventCount++;
+ timeBase = value;
+ if (timeBase - lastTimeBase > interval) {
+ Events.Add (eventCount);
+ eventCount = 0;
+ lastTimeBase = timeBase;
+ }
+ }
+ }
+
+ long lookupThread;
+ public long LookupThread {
+ get { return lookupThread; }
+ set { lookupThread = value; }
+ }
+
+ public Buffer CurrentBuffer {
+ get { return currentBuffer; }
+ set {
+ currentBuffer = value;
+ methodBase = currentBuffer.Header.MethodBase;
+ lastTimeBase = TimeBase = currentBuffer.Header.TimeBase;
+ if (!threadDictionary.TryGetValue (currentBuffer.Header.ThreadId, out currentThread)) {
+ currentThread = new ThreadContext () { ThreadId = currentBuffer.Header.ThreadId };
+ threadDictionary [currentBuffer.Header.ThreadId] = currentThread;
+ }
+ }
+ }
+
+ public class ThreadContext
+ {
+ public long ThreadId { get; set; }
+ public string Name { get; set; }
+
+ public Stack<MethodInfo> Stack = new Stack<MethodInfo> ();
+ public Stack<ulong> timeStack = new Stack<ulong> ();
+ public Stack<ulong> calleeTimeStack = new Stack<ulong> ();
+
+ public long LastTime { get; set; }
+
+ public void PushMethod (MethodInfo methodInfo, ulong timeStamp)
+ {
+ if (Stack.Count > 0) {
+ Stack.Peek ().CallStack.Add (methodInfo);
+ }
+ methodInfo.RecurseCount++;
+ methodInfo.Calls++;
+
+ timeStack.Push (timeStamp);
+ calleeTimeStack.Push (0);
+ Stack.Push (methodInfo);
+ }
+
+ public void PopMethod (MethodInfo methodInfo, ulong timeStamp)
+ {
+ methodInfo.RecurseCount--;
+ if (Stack.Count > 0 && Stack.Peek () == methodInfo) {
+ Stack.Pop ();
+ ulong timeDiff = timeStamp - timeStack.Pop ();
+ methodInfo.TimeWithChildren += timeDiff;
+ methodInfo.CalleeTime = calleeTimeStack.Pop ();
+ if (calleeTimeStack.Count > 0)
+ calleeTimeStack.Push (calleeTimeStack.Pop () + timeDiff);
+ }
+ }
+ }
+
+ public class MethodInfo
+ {
+ public long RecurseCount {
+ get;
+ set;
+ }
+
+ public ulong Calls {
+ get;
+ set;
+ }
+
+ public string Name {
+ get;
+ set;
+ }
+
+ public ulong TimeWithChildren {
+ get;
+ set;
+ }
+
+ public ulong CalleeTime {
+ get;
+ set;
+ }
+
+ public HashSet<MethodInfo> CallStack = new HashSet<MethodInfo> ();
+
+ public MethodInfo (string name)
+ {
+ this.Name = name;
+ }
+ }
+
+ public Dictionary<long, MethodInfo> methodDictionary = new Dictionary<long, MethodInfo> ();
+ public Dictionary<long, ThreadContext> threadDictionary = new Dictionary<long, ThreadContext> ();
+
+ public void Reset ()
+ {
+ Events.Clear ();
+ methodDictionary.Clear ();
+ threadDictionary.Clear ();
+ }
+
+ public override object Visit (MethodEvent methodEvent)
+ {
+ methodBase += methodEvent.Method;
+ TimeBase += methodEvent.TimeDiff;
+ switch (methodEvent.Type) {
+ case MethodEvent.MethodType.Jit:
+ methodDictionary [methodBase] = new MethodInfo (methodEvent.Name);
+ break;
+
+ case MethodEvent.MethodType.Enter:
+ if (ShouldLog) {
+ if (!methodDictionary.ContainsKey (methodBase))
+ methodDictionary [methodBase] = new MethodInfo ("Unknown method.");
+
+ currentThread.PushMethod (methodDictionary [methodBase], TimeBase);
+ }
+ break;
+
+ case MethodEvent.MethodType.Leave:
+ if (ShouldLog) {
+ if (!methodDictionary.ContainsKey (methodBase))
+ methodDictionary [methodBase] = new MethodInfo ("Unknown method.");
+ currentThread.PopMethod (methodDictionary [methodBase], TimeBase);
+ }
+ break;
+ }
+ return null;
+ }
+
+ bool ShouldLog {
+ get {
+ return (LookupThread == 0 || LookupThread == currentThread.ThreadId) &&
+ (StartTime == 0 && EndTime == 0 ||
+ StartTime < timeBase && timeBase < EndTime);
+ }
+ }
+
+ public override object Visit (ExceptionEvent exceptionEvent)
+ {
+ methodBase += exceptionEvent.Method;
+ TimeBase += exceptionEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (AllocEvent allocEvent)
+ {
+ TimeBase += allocEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (GcEvent gcEvent)
+ {
+ TimeBase += gcEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (HandleCreatedGcEvent handleCreatedGcEvent)
+ {
+ TimeBase += handleCreatedGcEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (HandleDestroyedGcEvent handleDestroyedGcEvent)
+ {
+ TimeBase += handleDestroyedGcEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (HeapEvent heapEvent)
+ {
+ TimeBase += heapEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (MetadataEvent metadataEvent)
+ {
+ TimeBase += metadataEvent.TimeDiff;
+ switch (metadataEvent.MType) {
+ case MetadataEvent.MetaDataType.Thread:
+ ThreadContext ctx;
+ long threadId = currentBuffer.Header.PtrBase * metadataEvent.Pointer;
+ if (!threadDictionary.TryGetValue (threadId, out ctx)) {
+ threadDictionary [threadId] = ctx = new ThreadContext () { ThreadId = threadId };
+ }
+ ctx.Name = metadataEvent.Name;
+ break;
+ }
+ return null;
+ }
+
+ public override object Visit (MonitiorEvent monitiorEvent)
+ {
+ TimeBase += monitiorEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (MoveGcEvent moveGcEvent)
+ {
+ TimeBase += moveGcEvent.TimeDiff;
+ return null;
+ }
+
+ public override object Visit (ResizeGcEvent resizeGcEvent)
+ {
+ TimeBase += resizeGcEvent.TimeDiff;
+ return null;
+ }
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionHandler.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionHandler.cs
new file mode 100644
index 0000000000..9bb1384e2c
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionHandler.cs
@@ -0,0 +1,114 @@
+//
+// ProfilerExecutionHandler.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using MonoDevelop.Core.Execution;
+using System.Diagnostics;
+using System.IO;
+using MonoDevelop.Ide;
+using System.Collections.Generic;
+using MonoDevelop.Core.Assemblies;
+using MonoDevelop.Core;
+using Gtk;
+
+namespace MonoDevelop.Profiler
+{
+ public class ProfilerStartInfo
+ {
+ public string Command {
+ get;
+ set;
+ }
+
+ public string Arguments {
+ get;
+ set;
+ }
+
+ public string WorkingDirectory {
+ get;
+ set;
+ }
+
+ Dictionary<string, string> environmentVariables;
+ public Dictionary<string, string> EnvironmentVariables {
+ get {
+ if (environmentVariables == null)
+ environmentVariables = new Dictionary<string,string> ();
+ return environmentVariables;
+ }
+ }
+
+ public bool UseExternalConsole { get; set; }
+
+ public bool CloseExternalConsoleOnExit { get; set; }
+
+ public ProfilerStartInfo (string monoRuntimePrefix, Dictionary<string,string> monoRuntimeEnvironmentVariables)
+ {
+ this.MonoRuntimePrefix = monoRuntimePrefix;
+ this.MonoRuntimeEnvironmentVariables = monoRuntimeEnvironmentVariables;
+ }
+
+ public string MonoRuntimePrefix { get; private set; }
+
+ public Dictionary<string,string> MonoRuntimeEnvironmentVariables { get; private set; }
+
+ /// <summary>
+ /// The session will output this to the debug log as soon as it starts. It can be used to log warnings from
+ /// creating the ProfilerStartInfo
+ /// </summary>
+ public string LogMessage { get; set; }
+ }
+
+ public class ProfilerExecutionHandler : IExecutionHandler
+ {
+ #region IExecutionHandler implementation
+ public bool CanExecute (ExecutionCommand command)
+ {
+ return command is DotNetExecutionCommand;
+ }
+
+ public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console)
+ {
+ var cmd = (DotNetExecutionCommand)command;
+ string tmpfile = System.IO.Path.GetTempFileName ();
+ string args = "--profile=log:output=" + tmpfile;
+ cmd.RuntimeArguments += args;
+ if (File.Exists (tmpfile))
+ File.Delete (tmpfile);
+ var result = cmd.TargetRuntime.GetExecutionHandler ().Execute (cmd, console);
+ result.Completed += delegate {
+ if (File.Exists (tmpfile)) {
+ Application.Invoke (delegate {
+ new ProfileDialog (tmpfile);
+ File.Delete (tmpfile);
+ });
+ }
+ };
+ return result;
+ }
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionModeSet.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionModeSet.cs
new file mode 100644
index 0000000000..28602b09ce
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/ProfilerExecutionModeSet.cs
@@ -0,0 +1,50 @@
+//
+// ProfilerExecutionModeSet.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using MonoDevelop.Core;
+using MonoDevelop.Core.Execution;
+
+namespace MonoDevelop.Profiler.Gui
+{
+ public class ProfilerExecutionModeSet: IExecutionModeSet
+ {
+ #region IExecutionModeSet implementation
+ public string Name {
+ get {
+ return GettextCatalog.GetString ("Profiler");
+ }
+ }
+
+ public IEnumerable<IExecutionMode> ExecutionModes {
+ get {
+ yield return new ExecutionMode ("Profiler", "Profiler", new ProfilerExecutionHandler ());
+ }
+ }
+ #endregion
+ }
+}
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeCellRenderer.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeCellRenderer.cs
new file mode 100644
index 0000000000..d2c8dc8407
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeCellRenderer.cs
@@ -0,0 +1,76 @@
+//
+// TimeCellRenderer.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Gtk;
+using Cairo;
+using Mono.TextEditor;
+
+namespace MonoDevelop.Profiler
+{
+ class TimeCellRenderer : CellRenderer
+ {
+ [GLib.Property ("time")]
+ public double Time {
+ get;
+ set;
+ }
+
+ public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
+ {
+ x_offset = y_offset = 0;
+ width = cell_area.Width;
+ height = cell_area.Height;
+ }
+
+ protected override void Render (Gdk.Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
+ {
+ using (Cairo.Context gr = Gdk.CairoHelper.Create (window)) {
+ gr.Rectangle (cell_area.X, cell_area.Y, cell_area.Width, cell_area.Height);
+ gr.Color = (HslColor)widget.Style.Base ((flags & CellRendererState.Selected) == CellRendererState.Selected ? StateType.Selected : StateType.Normal);
+ gr.Fill ();
+ var size = Math.Max (0, cell_area.Width - cell_area.Width * Time / 100.0);
+ var linearGradient = new LinearGradient (cell_area.X, cell_area.Y, cell_area.Right, cell_area.Bottom);
+ linearGradient.AddColorStop (0, new Cairo.Color (1, 0, 0));
+ linearGradient.AddColorStop (1, new Cairo.Color (1, 1, 1));
+ gr.Pattern = linearGradient;
+
+ gr.Rectangle (cell_area.X + size, cell_area.Y + 2, cell_area.Width - size, cell_area.Height - 4);
+ gr.Fill ();
+
+ var layout = gr.CreateLayout ();
+ layout.FontDescription = widget.PangoContext.FontDescription;
+ layout.SetText (string.Format ("{0:0.0}", Time));
+ int w, h;
+ layout.GetPixelSize (out w, out h);
+ gr.MoveTo (cell_area.X + cell_area.Width - 2 - w, cell_area.Y + (cell_area.Height - h) / 2);
+ gr.Color = new Cairo.Color (0, 0, 0);
+ gr.ShowLayout (layout);
+ layout.Dispose ();
+ }
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeLineWidget.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeLineWidget.cs
new file mode 100644
index 0000000000..e4a826dbad
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.Gui/TimeLineWidget.cs
@@ -0,0 +1,182 @@
+//
+// TimeLineWidget.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.ComponentModel;
+using Gtk;
+using Cairo;
+using Mono.TextEditor;
+
+namespace MonoDevelop.Profiler
+{
+ [ToolboxItem (true)]
+ public class TimeLineWidget : DrawingArea
+ {
+ ProfileDialog dialog;
+ int maxEvents = 230;
+
+ public TimeLineWidget (ProfileDialog dialog)
+ {
+ this.dialog = dialog;
+ Events |= Gdk.EventMask.ButtonMotionMask | Gdk.EventMask.PointerMotionMask | Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask;
+ }
+ double pressStart, pressEnd;
+ bool pressed;
+
+ protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
+ {
+ if (evnt.Button == 1) {
+ pressed = true;
+ pressStart = pressEnd = Math.Max (boxWidth, evnt.X);
+ }
+ return base.OnButtonPressEvent (evnt);
+ }
+
+ protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
+ {
+ var min = 100000 * (Math.Min (pressStart, pressEnd) - boxWidth);
+ var max = 100000 * (Math.Max (pressStart, pressEnd) - boxWidth);
+ dialog.SetTime ((ulong)min, (ulong)max);
+ pressed = false;
+ return base.OnButtonReleaseEvent (evnt);
+ }
+
+ protected override bool OnMotionNotifyEvent (Gdk.EventMotion evnt)
+ {
+ if (pressed) {
+ pressEnd = Math.Max (boxWidth, evnt.X);
+ QueueDraw ();
+ }
+ return base.OnMotionNotifyEvent (evnt);
+ }
+
+ protected override void OnSizeRequested (ref Requisition requisition)
+ {
+ base.OnSizeRequested (ref requisition);
+ }
+
+ const double timeHeight = 28;
+ const double eventHeight = 20;
+ const double boxWidth = 60;
+ const double eventMetricLength = 4;
+
+ static readonly Color timeGradientStartColor = new Color (0.85, 0.85, 0.85);
+ static readonly Color timeGradientEndColor = new Color (0.91, 0.91, 0.91);
+ static readonly Color lineColor = new Color (0.6, 0.6, 0.6);
+
+ void DrawBackground (Cairo.Context gr)
+ {
+ gr.Rectangle (0, 0, Allocation.Width, Allocation.Height);
+ gr.Color = new Color (1, 1, 1);
+ gr.Fill ();
+
+ gr.Rectangle (0, 0, Allocation.Width, timeHeight);
+ var gradient = new LinearGradient (0, 0, 0, timeHeight);
+ gradient.AddColorStop (0, timeGradientStartColor);
+ gradient.AddColorStop (1, timeGradientEndColor);
+ gr.Pattern = gradient;
+ gr.Fill ();
+
+ gr.LineWidth = 1;
+ gr.Color = lineColor;
+ gr.MoveTo (0, timeHeight + 0.5);
+ gr.LineTo (Allocation.Width, timeHeight + 0.5);
+ gr.Stroke ();
+
+ gr.MoveTo (0, timeHeight + eventHeight + 0.5);
+ gr.LineTo (Allocation.Width, timeHeight + eventHeight + 0.5);
+ gr.Stroke ();
+
+ gr.MoveTo (boxWidth + 0.5, 0);
+ gr.LineTo (boxWidth + 0.5, Allocation.Height);
+ gr.Stroke ();
+ }
+
+ protected override bool OnExposeEvent (Gdk.EventExpose evnt)
+ {
+ using (var gr = Gdk.CairoHelper.Create (evnt.Window)) {
+ DrawBackground (gr);
+
+ var layout = gr.CreateLayout ();
+ layout.FontDescription = Pango.FontDescription.FromString ("Tahoma 8");
+ layout.SetText ("Time");
+ int w, h;
+ layout.GetPixelSize (out w, out h);
+ gr.MoveTo ((boxWidth - w) / 2, (timeHeight - h) / 2);
+ gr.ShowLayout (layout);
+
+ layout.SetText ("Events");
+ layout.GetPixelSize (out w, out h);
+ gr.MoveTo ((boxWidth - w) / 2, timeHeight + (eventHeight - h) / 2);
+ gr.ShowLayout (layout);
+
+ for (int i = 100; i < maxEvents; i += 100) {
+ layout.SetText (i.ToString ());
+ layout.GetPixelSize (out w, out h);
+ double y = Allocation.Height - i * (Allocation.Height - timeHeight - eventHeight) / maxEvents;
+ gr.MoveTo (boxWidth - w - eventMetricLength - 2, y - h / 2);
+ gr.ShowLayout (layout);
+
+ gr.MoveTo (boxWidth - eventMetricLength, y);
+ gr.LineTo (boxWidth, y);
+ gr.Stroke ();
+ }
+ var eventMetricHeight = Allocation.Height - timeHeight - eventHeight;
+ gr.MoveTo (boxWidth + 1, Allocation.Height);
+ gr.Color = new Color (1, 0, 0);
+ for (int i = 0; i < dialog.visitor.Events.Count; i++) {
+ var e = dialog.visitor.Events [i];
+ gr.LineTo (boxWidth + 1 + i * 2, Allocation.Height - (eventMetricHeight * e / (double)maxEvents));
+ }
+ gr.Stroke ();
+
+ gr.Color = lineColor;
+ gr.MoveTo (boxWidth + 1 + dialog.visitor.Events.Count * 2, 0);
+ gr.LineTo (boxWidth + 1 + dialog.visitor.Events.Count * 2, 4);
+ gr.Stroke ();
+
+ layout.SetText (string.Format ("{0:0.0}ms", dialog.totalTime / 1000000));
+ layout.GetPixelSize (out w, out h);
+ gr.MoveTo (boxWidth + 1 + dialog.visitor.Events.Count * 2 - w / 2, 5);
+ gr.ShowLayout (layout);
+
+ layout.Dispose ();
+
+ gr.Rectangle (pressStart, 0, pressEnd - pressStart, Allocation.Height);
+ gr.Color = new Color (0, 1, 1, 0.2);
+ gr.Fill ();
+
+ gr.Color = new Color (0, 1, 1, 0.3);
+ gr.MoveTo (pressStart, 0);
+ gr.LineTo (pressStart, Allocation.Height);
+ gr.MoveTo (pressEnd, 0);
+ gr.LineTo (pressEnd, Allocation.Height);
+ gr.Stroke ();
+ }
+
+ return base.OnExposeEvent (evnt);
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.addin.xml b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.addin.xml
new file mode 100644
index 0000000000..90f6e4235f
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.addin.xml
@@ -0,0 +1,28 @@
+<Addin
+ id = "Profiler"
+ namespace = "MonoDevelop"
+ name = "Profiler"
+ author = "Mike Krüger"
+ copyright = "X11"
+ url = "http://www.monodevelop.com/"
+ description = "Provides a gui for the mono logging profiler"
+ category = "IDE extensions"
+ version = "2.4">
+
+ <Runtime>
+ <Import assembly = "MonoDevelop.Profiler.dll"/>
+ </Runtime>
+
+ <Dependencies>
+ <Addin id="Core" version="2.4"/>
+ <Addin id="Ide" version="2.4"/>
+ </Dependencies>
+
+ <!-- Extension Points -->
+
+ <!-- Extensions -->
+
+ <Extension path = "/MonoDevelop/Core/ExecutionModes">
+ <ModeSetType class="MonoDevelop.Profiler.Gui.ProfilerExecutionModeSet"/>
+ </Extension>
+</Addin>
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.csproj b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.csproj
new file mode 100644
index 0000000000..d73ea55220
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.csproj
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{EB37652A-0E94-4AFE-BAD6-72586628FF3A}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>MonoDevelop.Profiler</RootNamespace>
+ <AssemblyName>MonoDevelop.Profiler</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\..\build\AddIns</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <PlatformTarget>x86</PlatformTarget>
+ <ConsolePause>false</ConsolePause>
+ <CustomCommands>
+ <CustomCommands>
+ <Command type="Execute" command="make run" workingdir="/home/mkrueger/monodevelop/main" />
+ </CustomCommands>
+ </CustomCommands>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <DebugType>none</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\..\build\AddIns</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <PlatformTarget>x86</PlatformTarget>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="Mono.Posix" />
+ <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <Reference Include="System.Core" />
+ <Reference Include="MonoDevelop.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\build\bin\MonoDevelop.Core.dll</HintPath>
+ <Private>False</Private>
+ <Package>monodevelop</Package>
+ </Reference>
+ <Reference Include="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\build\bin\MonoDevelop.Ide.dll</HintPath>
+ <Private>False</Private>
+ <Package>monodevelop</Package>
+ </Reference>
+ <Reference Include="Mono.Addins, Version=0.5.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
+ <Reference Include="Mono.Cairo" />
+ <Reference Include="Mono.TextEditor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\build\bin\Mono.TextEditor.dll</HintPath>
+ <Package>monodevelop</Package>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="gtk-gui\gui.stetic">
+ <LogicalName>gui.stetic</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="MonoDevelop.Profiler.addin.xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="gtk-gui\generated.cs" />
+ <Compile Include="AssemblyInfo.cs" />
+ <Compile Include="MonoDevelop.Profiler\Buffer.cs" />
+ <Compile Include="MonoDevelop.Profiler\Event.cs" />
+ <Compile Include="MonoDevelop.Profiler\Header.cs" />
+ <Compile Include="MonoDevelop.Profiler\LogBuffer.cs" />
+ <Compile Include="MonoDevelop.Profiler.Gui\ProfileDialog.cs" />
+ <Compile Include="gtk-gui\MonoDevelop.Profiler.ProfileDialog.cs" />
+ <Compile Include="MonoDevelop.Profiler.Gui\TimeLineWidget.cs" />
+ <Compile Include="MonoDevelop.Profiler.Gui\TimeCellRenderer.cs" />
+ <Compile Include="MonoDevelop.Profiler\EventVisitor.cs" />
+ <Compile Include="MonoDevelop.Profiler\Util.cs" />
+ <Compile Include="MonoDevelop.Profiler.Gui\ProfilerExecutionModeSet.cs" />
+ <Compile Include="MonoDevelop.Profiler.Gui\ProfilerExecutionHandler.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ProjectExtensions>
+ <MonoDevelop>
+ <Properties InternalTargetFrameworkVersion="3.5">
+ <Policies>
+ <StandardHeader inheritsSet="MITX11License" />
+ </Policies>
+ </Properties>
+ </MonoDevelop>
+ </ProjectExtensions>
+ <ItemGroup>
+ <Folder Include="MonoDevelop.Profiler\" />
+ <Folder Include="MonoDevelop.Profiler.Gui\" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.sln b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.sln
new file mode 100644
index 0000000000..26c1dd842f
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Profiler", "MonoDevelop.Profiler.csproj", "{EB37652A-0E94-4AFE-BAD6-72586628FF3A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EB37652A-0E94-4AFE-BAD6-72586628FF3A}.Debug|x86.ActiveCfg = Debug|x86
+ {EB37652A-0E94-4AFE-BAD6-72586628FF3A}.Debug|x86.Build.0 = Debug|x86
+ {EB37652A-0E94-4AFE-BAD6-72586628FF3A}.Release|x86.ActiveCfg = Release|x86
+ {EB37652A-0E94-4AFE-BAD6-72586628FF3A}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = Mono.ProfilerGui\MonoDevelop.Profiler.csproj
+ EndGlobalSection
+EndGlobal
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Header.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Header.cs
new file mode 100644
index 0000000000..879df5c4b2
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Header.cs
@@ -0,0 +1,67 @@
+//
+// Header.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.IO;
+
+namespace MonoDevelop.Profiler
+{
+ public class Header
+ {
+ const int LogHeaderId = 0x4D505A01;
+
+ public readonly int Id; // constant value: LOG_HEADER_ID
+ public readonly byte Major, Minor; // major and minor version of the log profiler
+ public readonly byte Format; // version of the data format for the rest of the file
+ public readonly byte PtrSize; // size in bytes of a pointer in the profiled program
+ public readonly ulong StartupTime; // time in milliseconds since the unix epoch when the program started
+ public readonly int TimerOverhead; // approximate overhead in nanoseconds of the timer
+ public readonly int Flags; // file format flags, should be 0 for now
+ public readonly int Pid; // pid of the profiled process
+ public readonly int SysId; // operating system and architecture identifier
+
+ protected Header (BinaryReader reader)
+ {
+ Id = reader.ReadInt32 ();
+ if (Id != LogHeaderId)
+ throw new InvalidOperationException ("Id doesn't match.");
+ Major = reader.ReadByte ();
+ Minor = reader.ReadByte ();
+ Format = reader.ReadByte ();
+ PtrSize = reader.ReadByte ();
+ StartupTime = reader.ReadUInt64 ();
+ TimerOverhead = reader.ReadInt32 ();
+ Flags = reader.ReadInt32 ();
+ Pid = reader.ReadInt32 ();
+ SysId = reader.ReadInt32 ();
+ }
+
+ public static Header Read (BinaryReader reader)
+ {
+ return new Header (reader);
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/LogBuffer.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/LogBuffer.cs
new file mode 100644
index 0000000000..4bfbf4748f
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/LogBuffer.cs
@@ -0,0 +1,57 @@
+//
+// LogBuffer.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Profiler
+{
+ public class LogBuffer
+ {
+ public readonly Header Header;
+ public readonly List<Buffer> buffers = new List<Buffer> ();
+
+ public static LogBuffer Read (string fileName)
+ {
+ if (!File.Exists (fileName))
+ return null;
+ BinaryReader reader = new BinaryReader (File.OpenRead (fileName));
+ LogBuffer result = new LogBuffer (reader);
+ reader.Close ();
+ return result;
+ }
+
+ LogBuffer (BinaryReader reader)
+ {
+ this.Header = Header.Read (reader);
+ while (reader.BaseStream.Position < reader.BaseStream.Length) {
+ buffers.Add (Buffer.Read (reader));
+ }
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Util.cs b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Util.cs
new file mode 100644
index 0000000000..a8adea365a
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/MonoDevelop.Profiler/Util.cs
@@ -0,0 +1,79 @@
+//
+// Event.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+namespace MonoDevelop.Profiler
+{
+ public static class Util
+ {
+ public static ulong ReadULeb128 (this BinaryReader reader)
+ {
+ ulong result = 0;
+ int shift = 0;
+ while (true) {
+ byte b = reader.ReadByte ();
+ result |= ((ulong)(b & 0x7f)) << shift;
+ if ((b & 0x80) != 0x80)
+ break;
+ shift += 7;
+ }
+ return result;
+ }
+
+ public static long ReadSLeb128 (this BinaryReader reader)
+ {
+ long result = 0;
+ int shift = 0;
+ while (true) {
+ byte b = reader.ReadByte ();
+ result |= ((long)(b & 0x7f)) << shift;
+ shift += 7;
+ if ((b & 0x80) != 0x80) {
+ if (shift < sizeof(long) * 8 && (b & 0x40) == 0x40)
+ result |= -(1L << shift);
+ break;
+ }
+ }
+ return result;
+ }
+
+ public static string ReadNullTerminatedString (this BinaryReader reader)
+ {
+ List<byte> bytes = new List<byte> ();
+ while (true) {
+ byte b = reader.ReadByte ();
+ if (b == 0)
+ break;
+ bytes.Add (b);
+ }
+ return Encoding.UTF8.GetString (bytes.ToArray ());
+ }
+
+ }
+}
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/MonoDevelop.Profiler.ProfileDialog.cs b/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/MonoDevelop.Profiler.ProfileDialog.cs
new file mode 100644
index 0000000000..ae6003ae17
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/MonoDevelop.Profiler.ProfileDialog.cs
@@ -0,0 +1,79 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace MonoDevelop.Profiler
+{
+ public partial class ProfileDialog
+ {
+ private global::Gtk.VBox vbox1;
+ private global::Gtk.ScrolledWindow scrolledwindow1;
+ private global::Gtk.HBox hbox1;
+ private global::Gtk.Label label1;
+ private global::Gtk.ComboBox comboboxThreads;
+ private global::Gtk.ScrolledWindow GtkScrolledWindow;
+ private global::Gtk.TreeView profileResultsView;
+
+ protected virtual void Build ()
+ {
+ global::Stetic.Gui.Initialize (this);
+ // Widget MonoDevelop.Profiler.ProfileDialog
+ this.Name = "MonoDevelop.Profiler.ProfileDialog";
+ this.Title = global::Mono.Unix.Catalog.GetString ("ProfileDialog");
+ this.WindowPosition = ((global::Gtk.WindowPosition)(4));
+ // Container child MonoDevelop.Profiler.ProfileDialog.Gtk.Container+ContainerChild
+ this.vbox1 = new global::Gtk.VBox ();
+ this.vbox1.Name = "vbox1";
+ this.vbox1.Spacing = 6;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.scrolledwindow1 = new global::Gtk.ScrolledWindow ();
+ this.scrolledwindow1.CanFocus = true;
+ this.scrolledwindow1.Name = "scrolledwindow1";
+ this.scrolledwindow1.ShadowType = ((global::Gtk.ShadowType)(1));
+ this.vbox1.Add (this.scrolledwindow1);
+ global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox1 [this.scrolledwindow1]));
+ w1.Position = 0;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.hbox1 = new global::Gtk.HBox ();
+ this.hbox1.Name = "hbox1";
+ this.hbox1.Spacing = 6;
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.label1 = new global::Gtk.Label ();
+ this.label1.Name = "label1";
+ this.label1.LabelProp = global::Mono.Unix.Catalog.GetString ("Threads:");
+ this.hbox1.Add (this.label1);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.label1]));
+ w2.Position = 0;
+ w2.Expand = false;
+ w2.Fill = false;
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.comboboxThreads = global::Gtk.ComboBox.NewText ();
+ this.comboboxThreads.Name = "comboboxThreads";
+ this.hbox1.Add (this.comboboxThreads);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.comboboxThreads]));
+ w3.Position = 1;
+ this.vbox1.Add (this.hbox1);
+ global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox1 [this.hbox1]));
+ w4.Position = 1;
+ w4.Expand = false;
+ w4.Fill = false;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.GtkScrolledWindow = new global::Gtk.ScrolledWindow ();
+ this.GtkScrolledWindow.Name = "GtkScrolledWindow";
+ this.GtkScrolledWindow.ShadowType = ((global::Gtk.ShadowType)(1));
+ // Container child GtkScrolledWindow.Gtk.Container+ContainerChild
+ this.profileResultsView = new global::Gtk.TreeView ();
+ this.profileResultsView.CanFocus = true;
+ this.profileResultsView.Name = "profileResultsView";
+ this.GtkScrolledWindow.Add (this.profileResultsView);
+ this.vbox1.Add (this.GtkScrolledWindow);
+ global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox1 [this.GtkScrolledWindow]));
+ w6.Position = 2;
+ this.Add (this.vbox1);
+ if ((this.Child != null)) {
+ this.Child.ShowAll ();
+ }
+ this.DefaultWidth = 400;
+ this.DefaultHeight = 300;
+ this.Show ();
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/generated.cs b/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/generated.cs
new file mode 100644
index 0000000000..9ef3363981
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/generated.cs
@@ -0,0 +1,29 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace Stetic
+{
+ internal class Gui
+ {
+ private static bool initialized;
+
+ internal static void Initialize (Gtk.Widget iconRenderer)
+ {
+ if ((Stetic.Gui.initialized == false)) {
+ Stetic.Gui.initialized = true;
+ }
+ }
+ }
+
+ internal class ActionGroups
+ {
+ public static Gtk.ActionGroup GetActionGroup (System.Type type)
+ {
+ return Stetic.ActionGroups.GetActionGroup (type.FullName);
+ }
+
+ public static Gtk.ActionGroup GetActionGroup (string name)
+ {
+ return null;
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/gui.stetic b/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/gui.stetic
new file mode 100644
index 0000000000..00c0ef271b
--- /dev/null
+++ b/main/src/addins/MonoDevelop.ProfilerGui/gtk-gui/gui.stetic
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<stetic-interface>
+ <configuration>
+ <images-root-path>..</images-root-path>
+ <target-gtk-version>2.12</target-gtk-version>
+ </configuration>
+ <import>
+ <widget-library name="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <widget-library name="../../../../../build/bin/MonoDevelop.Ide.dll" />
+ <widget-library name="../../../../../build/bin/Mono.TextEditor.dll" />
+ <widget-library name="../../../../../build/AddIns/MonoDevelop.Profiler.dll" internal="true" />
+ </import>
+ <widget class="Gtk.Window" id="MonoDevelop.Profiler.ProfileDialog" design-size="400 300">
+ <property name="MemberName" />
+ <property name="Title" translatable="yes">ProfileDialog</property>
+ <property name="WindowPosition">CenterOnParent</property>
+ <child>
+ <widget class="Gtk.VBox" id="vbox1">
+ <property name="MemberName" />
+ <property name="Spacing">6</property>
+ <child>
+ <widget class="Gtk.ScrolledWindow" id="scrolledwindow1">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="ShadowType">In</property>
+ <child>
+ <widget class="Gtk.Viewport" id="GtkViewport">
+ <property name="MemberName" />
+ <property name="ShadowType">None</property>
+ <child>
+ <placeholder />
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="Position">0</property>
+ <property name="AutoSize">True</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.HBox" id="hbox1">
+ <property name="MemberName" />
+ <property name="Spacing">6</property>
+ <child>
+ <widget class="Gtk.Label" id="label1">
+ <property name="MemberName" />
+ <property name="LabelProp" translatable="yes">Threads:</property>
+ </widget>
+ <packing>
+ <property name="Position">0</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.ComboBox" id="comboboxThreads">
+ <property name="MemberName" />
+ <property name="IsTextCombo">True</property>
+ <property name="Items" translatable="yes" />
+ </widget>
+ <packing>
+ <property name="Position">1</property>
+ <property name="AutoSize">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="Position">1</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.ScrolledWindow" id="GtkScrolledWindow">
+ <property name="MemberName" />
+ <property name="ShadowType">In</property>
+ <child>
+ <widget class="Gtk.TreeView" id="profileResultsView">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="ShowScrollbars">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="Position">2</property>
+ <property name="AutoSize">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</stetic-interface> \ No newline at end of file