/// <summary> /// Dumps the profiled data of the given node. /// </summary> /// <param name="node">The node. Can be <see langword="false"/> to use the root node.</param> /// <param name="maxLevelIncluded"> /// The maximal level included relative to the given node. 0 means, no child data is included. /// 1 means, one level of children are included. /// </param> /// <returns> /// A string representing the profiled data. /// </returns> public string Dump(HierarchicalProfilerNode node, int maxLevelIncluded) { if (maxLevelIncluded < 0 || FrameCount == 0) { return(string.Empty); } if (node == null) { node = Root; } var stringBuilder = new StringBuilder(); TimeSpan totalTime = (node == Root) ? ElapsedTime : node.Sum; stringBuilder.Append(Name); stringBuilder.Append("."); stringBuilder.Append(node.Name); stringBuilder.Append(" "); stringBuilder.Append(FrameCount); stringBuilder.Append(" frames "); AppendTime(stringBuilder, new TimeSpan(totalTime.Ticks / FrameCount)); stringBuilder.Append("/frame "); AppendTime(stringBuilder, totalTime); stringBuilder.Append(" total"); stringBuilder.AppendLine(); Dump(stringBuilder, node, 1, maxLevelIncluded, totalTime); return(stringBuilder.ToString()); }
/// <summary> /// Initializes a new instance of the <see cref="HierarchicalProfilerNode"/> class. /// </summary> /// <param name="name">The name.</param> /// <param name="parent">The parent.</param> internal HierarchicalProfilerNode(string name, HierarchicalProfilerNode parent) { Name = name; Profiler = parent.Profiler; Parent = parent; Reset(); }
/// <summary> /// Gets a node with the given name. If no child with this name exists, a new child is appended. /// </summary> /// <param name="nodeName">The name of the node.</param> /// <returns>The child node.</returns> internal HierarchicalProfilerNode GetSubNode(string nodeName) { var child = FirstChild; while (child != null) { if (child.Name == nodeName) { return(child); } child = child.NextSibling; } // Did not find a matching child node. --> Add new child. var node = new HierarchicalProfilerNode(nodeName, this); if (LastChild == null) { Debug.Assert(FirstChild == null); Debug.Assert(LastChild == null); FirstChild = node; LastChild = node; } else { LastChild.NextSibling = node; LastChild = node; } return(node); }
/// <summary> /// Dumps the specified string builder (recursive). /// </summary> private void Dump(StringBuilder stringBuilder, HierarchicalProfilerNode node, int level, int maxLevelIncluded, TimeSpan totalTime) { if (level > maxLevelIncluded) { return; } TimeSpan childrenSum = TimeSpan.Zero; int numberOfChildren = 0; foreach (var child in node.Children) { numberOfChildren++; childrenSum += child.Sum; for (int i = 0; i < level; i++) { stringBuilder.Append(" "); } stringBuilder.Append(child.Name); stringBuilder.Append(" "); stringBuilder.Append(((double)child.Sum.Ticks / totalTime.Ticks).ToString("0.##% ", CultureInfo.InvariantCulture)); //AppendTime(stringBuilder, child.Sum); //stringBuilder.Append(" "); AppendTime(stringBuilder, new TimeSpan(child.Sum.Ticks / FrameCount)); stringBuilder.Append("/frame "); stringBuilder.Append(((double)child.Count / FrameCount).ToString("0.###", CultureInfo.InvariantCulture)); stringBuilder.Append(" calls/frame ("); AppendTime(stringBuilder, child.Minimum); stringBuilder.Append("/"); AppendTime(stringBuilder, child.Average); stringBuilder.Append("/"); AppendTime(stringBuilder, child.Maximum); stringBuilder.AppendLine(")"); Dump(stringBuilder, child, level + 1, maxLevelIncluded, totalTime); } if (numberOfChildren > 0) { for (int i = 0; i < level; i++) { stringBuilder.Append(" "); } stringBuilder.Append("Other "); TimeSpan unaccountedTime = (node == Root ? ElapsedTime : node.Sum) - childrenSum; stringBuilder.Append(((double)unaccountedTime.Ticks / totalTime.Ticks).ToString("0.##% ", CultureInfo.InvariantCulture)); AppendTime(stringBuilder, unaccountedTime); stringBuilder.Append(" "); AppendTime(stringBuilder, new TimeSpan(unaccountedTime.Ticks / FrameCount)); stringBuilder.Append("/frame "); stringBuilder.AppendLine(); } }
//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- /// <summary> /// Initializes a new instance of the <see cref="HierarchicalProfiler"/> class. /// </summary> /// <param name="name">The name of this profiler.</param> public HierarchicalProfiler(string name) { #if PORTABLE throw Portable.NotImplementedException; #elif SILVERLIGHT throw new NotSupportedException(); #else Name = name; Root = new HierarchicalProfilerNode("Root", this); CurrentNode = Root; Stopwatch = System.Diagnostics.Stopwatch.StartNew(); #endif }
/// <summary> /// Gets a node with the given name. If no child with this name exists, a new child is appended. /// </summary> /// <param name="nodeName">The name of the node.</param> /// <returns>The child node.</returns> internal HierarchicalProfilerNode GetSubNode(string nodeName) { var child = FirstChild; while (child != null) { if (child.Name == nodeName) return child; child = child.NextSibling; } // Did not find a matching child node. --> Add new child. var node = new HierarchicalProfilerNode(nodeName, this); if (LastChild == null) { Debug.Assert(FirstChild == null); Debug.Assert(LastChild == null); FirstChild = node; LastChild = node; } else { LastChild.NextSibling = node; LastChild = node; } return node; }
/// <summary> /// Dumps the specified string builder (recursive). /// </summary> private void Dump(StringBuilder stringBuilder, HierarchicalProfilerNode node, int level, int maxLevelIncluded, TimeSpan totalTime) { if (level > maxLevelIncluded) return; TimeSpan childrenSum = TimeSpan.Zero; int numberOfChildren = 0; foreach (var child in node.Children) { numberOfChildren++; childrenSum += child.Sum; for (int i = 0; i < level; i++) stringBuilder.Append(" "); stringBuilder.Append(child.Name); stringBuilder.Append(" "); stringBuilder.Append(((double)child.Sum.Ticks / totalTime.Ticks).ToString("0.##% ", CultureInfo.InvariantCulture)); //AppendTime(stringBuilder, child.Sum); //stringBuilder.Append(" "); AppendTime(stringBuilder, new TimeSpan(child.Sum.Ticks / FrameCount)); stringBuilder.Append("/frame "); stringBuilder.Append(((double)child.Count / FrameCount).ToString("0.###", CultureInfo.InvariantCulture)); stringBuilder.Append(" calls/frame ("); AppendTime(stringBuilder, child.Minimum); stringBuilder.Append("/"); AppendTime(stringBuilder, child.Average); stringBuilder.Append("/"); AppendTime(stringBuilder, child.Maximum); stringBuilder.AppendLine(")"); Dump(stringBuilder, child, level + 1, maxLevelIncluded, totalTime); } if (numberOfChildren > 0) { for (int i = 0; i < level; i++) stringBuilder.Append(" "); stringBuilder.Append("Other "); TimeSpan unaccountedTime = (node == Root ? ElapsedTime : node.Sum) - childrenSum; stringBuilder.Append(((double)unaccountedTime.Ticks / totalTime.Ticks).ToString("0.##% ", CultureInfo.InvariantCulture)); AppendTime(stringBuilder, unaccountedTime); stringBuilder.Append(" "); AppendTime(stringBuilder, new TimeSpan(unaccountedTime.Ticks / FrameCount)); stringBuilder.Append("/frame "); stringBuilder.AppendLine(); } }
public void Stop() { // Ignore any calls before the first NewFrame call. This occurs when Reset() // is called in the middle of profiling. if (FrameCount <= 0) return; bool noRecursion = CurrentNode.Return(); if (noRecursion) CurrentNode = CurrentNode.Parent; }
public void Start(string nodeName) { // Ignore any calls before the first NewFrame call. This occurs when Reset() // is called in the middle of profiling. if (FrameCount <= 0) return; if (nodeName != CurrentNode.Name) CurrentNode = CurrentNode.GetSubNode(nodeName); CurrentNode.Call(); }
public void Reset() { Root.Reset(); CurrentNode = Root; FrameCount = 0; #if !PORTABLE && !SILVERLIGHT Stopwatch.Reset(); Stopwatch.Start(); #endif }
/// <summary> /// Dumps the profiled data of the given node. /// </summary> /// <param name="node">The node. Can be <see langword="false"/> to use the root node.</param> /// <param name="maxLevelIncluded"> /// The maximal level included relative to the given node. 0 means, no child data is included. /// 1 means, one level of children are included. /// </param> /// <returns> /// A string representing the profiled data. /// </returns> public string Dump(HierarchicalProfilerNode node, int maxLevelIncluded) { if (maxLevelIncluded < 0 || FrameCount == 0) return string.Empty; if (node == null) node = Root; var stringBuilder = new StringBuilder(); TimeSpan totalTime = (node == Root) ? ElapsedTime : node.Sum; stringBuilder.Append(Name); stringBuilder.Append("."); stringBuilder.Append(node.Name); stringBuilder.Append(" "); stringBuilder.Append(FrameCount); stringBuilder.Append(" frames "); AppendTime(stringBuilder, new TimeSpan(totalTime.Ticks / FrameCount)); stringBuilder.Append("/frame "); AppendTime(stringBuilder, totalTime); stringBuilder.Append(" total"); stringBuilder.AppendLine(); Dump(stringBuilder, node, 1, maxLevelIncluded, totalTime); return stringBuilder.ToString(); }
//-------------------------------------------------------------- /// <summary> /// Initializes a new instance of the <see cref="HierarchicalProfiler"/> class. /// </summary> /// <param name="name">The name of this profiler.</param> public HierarchicalProfiler(string name) { #if PORTABLE throw Portable.NotImplementedException; #elif SILVERLIGHT throw new NotSupportedException(); #else Name = name; Root = new HierarchicalProfilerNode("Root", this); CurrentNode = Root; Stopwatch = System.Diagnostics.Stopwatch.StartNew(); #endif }