diff options
author | Mike Krüger <mkrueger@novell.com> | 2010-11-22 10:28:54 +0300 |
---|---|---|
committer | Mike Krüger <mkrueger@novell.com> | 2010-11-22 10:28:54 +0300 |
commit | fe512447d739b804ff781bac5dfd13ade750ca61 (patch) | |
tree | 9c9af6800f8ae5565a4f0c62a90a1f967325bca3 /main/src/addins/MonoDevelop.ProfilerGui | |
parent | dd3b3f7e852d0ddbdcc0e516e572a57bc244f44b (diff) |
Renamed directoryj
Diffstat (limited to 'main/src/addins/MonoDevelop.ProfilerGui')
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 |