Esempio n. 1
0
        private void CalcThreadline(long currentTick)
        {
            // clear thread map so order of items is kept and we dont get threads switching around
            RemoveLines.Clear();
            foreach (var timeline in Threadlines.Values)
            {
                timeline.Sequence.Clear();
                timeline.DepthSet.Clear();

                if (!timeline.IsAlive)
                {
                    RemoveLines.Add(timeline.ThreadID);
                }
            }

            foreach (var id in RemoveLines)
            {
                Threadlines.Remove(id);
            }

            AddedNodes.Clear();

            foreach (var flow in XRay.FlowMap)
            {
                if (ShowThreads != null && !ShowThreads.Contains(flow.ThreadID))
                {
                    continue;
                }

                if (ShowThreads == null && !flow.IsAlive)
                {
                    continue;
                }

                long startTick  = 0;
                int  startDepth = XRay.MaxStack;

                foreach (var item in flow.EnumerateThreadline())
                {
                    if (startTick == 0)
                    {
                        startTick = item.StartTick;
                    }

                    // we should be reading into the past, if the next item is
                    // in the future, then we are reading space that the app as logged
                    // since this process was started (its nice cause we avoid locks on the timeline
                    if (item.StartTick > startTick)
                    {
                        break;
                    }

                    if (AddToTimeline(flow, item))
                    {
                        if (item.Depth < startDepth)
                        {
                            startDepth = item.Depth;
                        }
                    }
                }

                // add stack items that have been pushed off threadline (functions that haven't exited yet)
                for (int i = startDepth - 1; i >= 0; i--)
                {
                    var item = flow.Stack[i];

                    if (item != null)
                    {
                        AddToTimeline(flow, item);
                    }
                }
            }

            // remove empty threads
            var removeTimelines = Threadlines.Values.Where(t => t.Sequence.Count == 0).ToArray();

            foreach (var timeline in removeTimelines)
            {
                Threadlines.Remove(timeline.ThreadID);
            }
        }
        public void Render()
        {
            // clear and pre-process marked depencies
            RecalcDependencies();

            // figure out if we need to do a search
            if (SearchString != LastSearch)
            {
                DoSearch();
            }

            // draw layout
            ScreenSize.Width  = Renderer.ViewWidth * ZoomFactor;
            ScreenSize.Height = Renderer.ViewHeight * ZoomFactor;
            ScreenOffset.X    = PanOffset.X * ScreenSize.Width;  // +(Width * CenterFactor.X - ModelSize.Width * CenterFactor.X);
            ScreenOffset.Y    = PanOffset.Y * ScreenSize.Height; // +(Height * CenterFactor.Y - ModelSize.Height * CenterFactor.Y);

            if (ViewLayout == LayoutType.TreeMap)
            {
                DrawTreeMap(Renderer);

                if (ShowingOutside)
                {
                    Renderer.DrawTextBackground(XColors.BorderColor, InternalRoot.AreaF.Width, 0, PanelBorderWidth, InternalRoot.AreaF.Height);
                    DrawNode(InternalRoot, 0, true);
                }

                if (ShowingExternal)
                {
                    Renderer.DrawTextBackground(XColors.BorderColor, ExternalRoot.AreaF.X - PanelBorderWidth, 0, PanelBorderWidth, ExternalRoot.AreaF.Height);
                    DrawNode(ExternalRoot, 0, true);
                }

                DrawNode(CurrentRoot, 0, true);
            }

            else if (ViewLayout == LayoutType.CallGraph)
            {
                DrawCallGraph();

                // id 0 nodes are intermediates
                foreach (var node in PositionMap.Values)
                {
                    //foreach (var node in Graphs.SelectMany(g => g.Nodes()).Where(n => n.ID != 0))
                    DrawNode(node, 0, false);
                }
            }

            else if (ViewLayout == LayoutType.Timeline)
            {
                DrawTheadline();

                foreach (var node in ThreadlineNodes)
                {
                    DrawNode(node.Node, node.Area, node.LabelArea, 0, false, node.ShowHit);
                }
            }


            // draw ignored over nodes ignored may contain

            /*foreach (var ignored in IgnoredNodes.Values)
             *  if (PositionMap.ContainsKey(ignored.ID))
             *  {
             *      Renderer.DrawLine(XColors.IgnoredColor, 1, ignored.AreaF.UpperLeftCorner(), ignored.AreaF.LowerRightCorner(), false);
             *      Renderer.DrawLine(XColors.IgnoredColor, 1, ignored.AreaF.UpperRightCorner(), ignored.AreaF.LowerLeftCorner(), false);
             *  }*/

            // draw dividers for call graph

            /*if (ViewLayout == LayoutType.CallGraph)
             * {
             *  if (ShowRightOutsideArea)
             *      buffer.DrawLine(CallDividerPen, RightDivider, 0, RightDivider, Height);
             *
             *  if (ShowLeftOutsideArea)
             *      buffer.DrawLine(CallDividerPen, LeftDivider, 0, LeftDivider, Height);
             * }*/


            // draw dependency graph
            if (ViewLayout == LayoutType.CallGraph &&
                (GraphMode == CallGraphMode.Dependencies ||
                 GraphMode == CallGraphMode.Init ||
                 GraphMode == CallGraphMode.Intermediates))
            {
                foreach (var source in PositionMap.Values)
                {
                    if (source.EdgesOut == null)
                    {
                        continue;
                    }

                    foreach (var to in source.EdgesOut)
                    {
                        if (!PositionMap.ContainsKey(to))
                        {
                            continue;
                        }

                        var destination = PositionMap[to];

                        int penWidth = (source.Focused || destination.Focused) ? 2 : 1;

                        if ((!DrawCallGraphVertically && source.AreaF.X < destination.AreaF.X) ||
                            (DrawCallGraphVertically && source.AreaF.Y < destination.AreaF.Y))
                        {
                            DrawGraphEdge(penWidth, XColors.CallOutColor, source, destination);
                        }
                        else
                        {
                            DrawGraphEdge(penWidth, XColors.CallInColor, source, destination);
                        }
                    }
                }
            }


            // draw call graph
            if (XRay.FlowTracking && ViewLayout != LayoutType.Timeline)
            {
                foreach (var source in PositionMap.Values)
                {
                    if (source.XNode.CallsOut == null)
                    {
                        continue;
                    }

                    if (ViewLayout == LayoutType.TreeMap && source.ObjType == XObjType.Class && ShowMethods)
                    {
                        continue;
                    }

                    if (ViewLayout == LayoutType.CallGraph &&
                        GraphMode != CallGraphMode.Init &&
                        source.ObjType == XObjType.Class &&
                        ShowMethods)
                    {
                        continue;
                    }


                    foreach (var call in source.XNode.CallsOut)
                    {
                        if (!PositionMap.ContainsKey(call.Destination))
                        {
                            continue;
                        }

                        if (ShowThreads != null && !call.ThreadIDs.Any(id => ShowThreads.Contains(id)))
                        {
                            continue;
                        }

                        var destination = PositionMap[call.Destination];

                        // if there are items we're filtering on then only show calls to those nodes
                        if (FilteredNodes.Count > 0 && !IsNodeFiltered(true, source) && !IsNodeFiltered(true, destination))
                        {
                            continue;
                        }

                        // do after select filter so we can have ignored nodes inside selected, but not the otherway around
                        if (IgnoredNodes.Count > 0 && IsNodeFiltered(false, source) || IsNodeFiltered(false, destination))
                        {
                            continue;
                        }

                        int lineWidth = (source.Focused || destination.Focused) ? 2 : 1;

                        if (call.StillInside > 0 && ShowCalls)
                        {
                            if (ViewLayout == LayoutType.TreeMap)
                            {
                                Renderer.DrawCallLine(XColors.HoldingCallColor, lineWidth, source.CenterF, destination.CenterF, false, source, destination);
                            }
                            else if (ViewLayout == LayoutType.CallGraph)
                            {
                                DrawGraphEdge(lineWidth, XColors.HoldingCallColor, source, destination);
                            }
                        }

                        else if (ShowAllCalls &&
                                 GraphMode != CallGraphMode.Intermediates &&
                                 GraphMode != CallGraphMode.Init)
                        {
                            if (ViewLayout == LayoutType.TreeMap)
                            {
                                var callSource = PositionMap[call.Source];
                                var callDest   = PositionMap[call.Destination];

                                PointF start = callSource.CenterF;
                                PointF end   = callDest.CenterF;
                                PointF mid   = new PointF(start.X + (end.X - start.X) / 2, start.Y + (end.Y - start.Y) / 2);

                                Renderer.DrawCallLine(XColors.CallOutColor, lineWidth, start, mid, false, callSource, callDest);
                                Renderer.DrawCallLine(XColors.CallInColor, lineWidth, mid, end, false, callSource, callDest);
                            }
                            else if (ViewLayout == LayoutType.CallGraph)
                            {
                                if ((!DrawCallGraphVertically && source.AreaF.X < destination.AreaF.X) ||
                                    (DrawCallGraphVertically && source.AreaF.Y < destination.AreaF.Y))
                                {
                                    DrawGraphEdge(lineWidth, XColors.CallOutColor, source, destination);
                                }
                                else
                                {
                                    DrawGraphEdge(lineWidth, XColors.CallInColor, source, destination);
                                }
                            }
                        }

                        if (call.Hit > 0 && ShowCalls)
                        {
                            var color = XColors.CallPenColors[call.Hit];

                            if (ViewLayout == LayoutType.TreeMap)
                            {
                                Renderer.DrawCallLine(color, lineWidth, source.CenterF, destination.CenterF, true, source, destination);
                            }

                            else if (ViewLayout == LayoutType.CallGraph)
                            {
                                DrawGraphEdge(lineWidth, color, source, destination, true);
                            }
                        }
                    }
                }
            }

            XRay.DashOffset = (XRay.DashOffset == 0) ? 2 : XRay.DashOffset - 1;

            // draw mouse over label
            if (ViewLayout != LayoutType.Timeline)
            {
                DrawFooterLabel();
            }

            DrawToolTip();
        }