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
        }