public void AddStack(SymbolicFrame[] frames, int index = 0)
        {
            _countAsNode++;

            var firstFrame = frames[index];

            // search if the frame to add has already been seen
            var callstack = Stacks.FirstOrDefault(s => string.CompareOrdinal(s.Symbol, firstFrame.Symbol) == 0);

            // if not, we are starting a new branch
            if (callstack == null)
            {
                callstack = new MergedSymbolicStacks(frames[index].Address, frames[index].Symbol);
                Stacks.Add(callstack);
            }

            // it was the last frame of the stack
            if (index == frames.Length - 1)
            {
                callstack._countAsLeaf++;
                return;
            }

            callstack.AddStack(frames, index + 1);
        }
        public bool Start(int pid)
        {
            if (_pid > 0)
            {
                throw new InvalidOperationException("Profiling session cannot be started more than once at a time...");
            }
            if (pid <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(pid), "Process ID must be greater than 0...");
            }

            _pid            = pid;
            _stackCount     = 0;
            _stacks         = new MergedSymbolicStacks();
            _missingSymbols = new Dictionary <TraceModuleFile, bool>();

            return(OnStart());
        }
        private static void RenderStack(MergedSymbolicStacks stack, IRenderer visitor, bool isRoot, int increment)
        {
            var alignment    = new string(' ', Padding *increment);
            var padding      = new string(' ', Padding);
            var currentFrame = stack.Frame;

            // special root case
            if (isRoot)
            {
                visitor.WriteCount($"{Environment.NewLine}{alignment}{stack.CountAsNode, Padding} ");
            }
            else
            {
                visitor.WriteCount($"{Environment.NewLine}{alignment}{stack.CountAsLeaf + stack.CountAsNode, Padding} ");
            }

            visitor.WriteMethod(stack.Symbol);

            var childrenCount = stack.Stacks.Count;

            if (childrenCount == 0)
            {
                visitor.WriteFrameSeparator("");
                return;
            }
            foreach (var nextStackFrame in stack.Stacks.OrderByDescending(s => s.CountAsNode + s.CountAsLeaf))
            {
                // increment when more than 1 children
                var childIncrement = (childrenCount == 1) ? increment : increment + 1;
                RenderStack(nextStackFrame, visitor, false, childIncrement);
                if (increment != childIncrement)
                {
                    visitor.WriteFrameSeparator($"{Environment.NewLine}{alignment}{padding}{nextStackFrame.CountAsNode + nextStackFrame.CountAsLeaf, Padding} ");
                    visitor.WriteFrameSeparator($"~~~~ ");
                }
            }
        }
 public static void Render(this MergedSymbolicStacks stacks, IRenderer visitor)
 {
     RenderStack(stacks, visitor, true, 0);
 }