public ProfilerCodeBlockInstance(ProfilerCodeBlock instanceOf, ProfilerCodeBlockInstance parent) { _instanceOf = instanceOf; _parent = parent; }
private void _GenerateOutputStringRecursive(ProfilerCodeBlockInstance instance, ref int depth, ref string output) { // generate spacing string to visually represent the hierarchy based on depth string depthSpace = " "; for (int i = 0; i < depth; ++i) depthSpace += " "; // get non-sub time and total time percentages double nsTime = (instance.NonSubTime / _totalTime) * 100; double totalTime = (instance.TotalTime / _totalTime) * 100; double avgTime = instance.TotalTime / instance.InvokeCount; // write this block instance output += string.Format("{0,7:0.000} {1,7:0.000} {2,8} {3,8:0.000} {4} {5}\n", totalTime, nsTime, instance.InvokeCount, avgTime, depthSpace, instance.InstanceOf.Name); IDictionaryEnumerator enumerator = instance._childHash.GetEnumerator(); List<ProfilerCodeBlockInstance> children = new List<ProfilerCodeBlockInstance>(); while (enumerator.MoveNext()) children.Add(enumerator.Value as ProfilerCodeBlockInstance); // check if this instance has any children if (children.Count > 0) { // sort the list of children // (defined by the IComparable implementation. // see ProfilerCodeBlockInstance.CompareTo) children.Sort(); //increment depth for child calls depth++; // recurse through children foreach (ProfilerCodeBlockInstance child in children) _GenerateOutputStringRecursive(child, ref depth, ref output); // decrement depth for sibling calls depth--; } }
/// <summary> /// This method was used to debug the profiler. It can tell you whether or not a code block instance that you want /// to add to the profiler's call stack is valid. /// </summary> /// <param name="blockInstance">The code block instance you're about to assign to _currentBlockInstance.</param> /// <returns>True if the code block instance is valid</returns> private bool _ValidateCodeBlockInstance(ProfilerCodeBlockInstance blockInstance) { ProfilerCodeBlockInstance mine, theirs; theirs = blockInstance.Parent; mine = _currentBlockInstance; while (theirs != null) { if (mine == null || mine.InstanceOf.Name != theirs.InstanceOf.Name) return false; theirs = theirs.Parent; mine = mine.Parent; } if (mine == null) return true; return false; }
public void StartBlock(ProfilerCodeBlock thisBlock) { #if TORQUE_PROFILE // increment stack depth _stackDepth++; // assert that stack depth is not huge if (_stackDepth >= _maxStackDepth) { // find the code block with the most invocations List<ProfilerCodeBlock> codeBlocks = _GetCodeBlocksList(); ProfilerCodeBlock block = codeBlocks[0]; foreach (ProfilerCodeBlock codeBlock in codeBlocks) if (codeBlock.InvokeCount > block.InvokeCount) block = codeBlock; Assert.Fatal(false, "Profiler.StartBlock - Stack overflow in profiler. Most likely culprit is: " + block.Name + " (" + block.InvokeCount.ToString() + " on stack)\n\nPlease make sure your StartBlock and EndBlock calls match up!"); } // make sure we're profiling if (!_isProfiling || thisBlock == null) return; // get the profiler code block instance object for this particular code path ProfilerCodeBlockInstance thisBlockInstance = null; // check for recursion if (_currentBlockInstance != null && _currentBlockInstance.InstanceOf == thisBlock) { // recursion: use the current code block rather than creating another instance thisBlockInstance = _currentBlockInstance; // increase the recursion depth of this instance thisBlockInstance.RecursionDepth++; } else { // check if this is a root instance bool isRoot = _currentBlockInstance == null; // check for the last seen instance if (!isRoot && _currentBlockInstance != null && _currentBlockInstance.LastSeenInstance != null && _currentBlockInstance.LastSeenInstance.InstanceOf == thisBlock) { // get the last seen instance on this code block thisBlockInstance = _currentBlockInstance.LastSeenInstance; } else { // get the existing block instance if (!isRoot) thisBlockInstance = _currentBlockInstance._childHash[thisBlock.Name] as ProfilerCodeBlockInstance; else thisBlockInstance = _rootBlockInstanceHash[thisBlock.Name] as ProfilerCodeBlockInstance; // create a code block instance for this section if none exists if (thisBlockInstance == null) { // create a new instance and hash it on the code block thisBlockInstance = new ProfilerCodeBlockInstance(thisBlock, _currentBlockInstance); // hash the instance on either the current code block, or the root hash if (!isRoot) _currentBlockInstance._childHash.Add(thisBlock.Name, thisBlockInstance); else _rootBlockInstanceHash.Add(thisBlock.Name, thisBlockInstance); } } // set the start time of the current pass long ticks; QueryPerformanceCounter(out ticks); thisBlockInstance.PassStartTime = ((double)ticks / (double)_tickFrequency) * 1000.0; // validate the current code block instance Assert.Fatal(_ValidateCodeBlockInstance(thisBlockInstance), "Profiler.StartBlock - Profiler doesn't support multiple code paths to the same child-parent code block pair. Email Adam Larson for details: [email protected]"); // record the last seen instance for fast lookups next time if (_currentBlockInstance != null) _currentBlockInstance.LastSeenInstance = thisBlockInstance; // push the new codeblock onto the stack _currentBlockInstance = thisBlockInstance; } // increment the invoke count thisBlock.InvokeCount++; thisBlockInstance.InvokeCount++; #endif // TORQUE_PROFILE }