public EventsThreadRow(FrameGroup group, ThreadDescription desc, ThreadData data)
        {
            Description = desc;
            EventData   = data;
            Group       = group;
            MaxDepth    = 1;

            Header = new ThreadNameView()
            {
                DataContext = this
            };

            UpdateThreadsDepth();

            switch (Controls.Settings.LocalSettings.Data.ThreadExpandMode)
            {
            case Controls.LocalSettings.ExpandMode.CollapseAll:
                _isExpanded = false;
                break;

            case Controls.LocalSettings.ExpandMode.ExpandAll:
                _isExpanded = true;
                break;

            case Controls.LocalSettings.ExpandMode.ExpandMain:
                _isExpanded = group.MainThread.Description == desc;
                break;
            }
        }
Exemple #2
0
        private static ProcessGroup GetProcessGroup(FrameGroup group, UInt64 threadID)
        {
            if (threadID == 0)
            {
                return(ProcessGroup.None);
            }

            ThreadData thread = group.GetThread(threadID);

            if (thread != null)
            {
                return(ProcessGroup.CurrentProcess);
            }

            ThreadDescription desc = null;

            if (group.Board.ThreadDescriptions.TryGetValue(threadID, out desc))
            {
                if (desc.IsIdle)
                {
                    return(ProcessGroup.None);
                }
            }

            return(ProcessGroup.OtherProcess);
        }
Exemple #3
0
        public EventsThreadRow(FrameGroup group, ThreadDescription desc, ThreadData data, ThreadViewSettings settings)
        {
            Description = desc;
            EventData   = data;
            Group       = group;
            MaxDepth    = 1;
            Settings    = settings;

            Header = new ThreadNameView()
            {
                DataContext = this
            };

            UpdateThreadsDepth();

            switch (Settings?.ThreadExpandMode)
            {
            case ExpandMode.CollapseAll:
                _isExpanded = false;
                break;

            case ExpandMode.ExpandAll:
                _isExpanded = true;
                break;

            case ExpandMode.ExpandMain:
                _isExpanded = desc.ThreadIndex == group.Board.MainThreadIndex;
                break;
            }
        }
Exemple #4
0
        List <EventsThreadRow> GenerateThreadRows(FrameGroup group)
        {
            id2row.Clear();

            List <EventsThreadRow> eventThreads = new List <EventsThreadRow>();

            for (int i = 0; i < Math.Min(group.Board.Threads.Count, group.Threads.Count); ++i)
            {
                ThreadData        data   = group.Threads[i];
                ThreadDescription thread = data.Description;

                if (thread.IsIdle)
                {
                    continue;
                }

                bool threadHasData = false;
                if (data.Events != null)
                {
                    double duration = 0.0;
                    foreach (EventFrame frame in data.Events)
                    {
                        duration += frame.Duration;
                        if (duration > MIN_THREAD_ACCUMULATED_DURATION)
                        {
                            threadHasData = true;
                            break;
                        }
                    }
                }

                if (thread.Origin == ThreadDescription.Source.Core)
                {
                    threadHasData = true;
                }

                if (threadHasData)
                {
                    EventsThreadRow row = new EventsThreadRow(group, thread, data, Settings);
                    eventThreads.Add(row);

                    id2row.Add(row.Description.ThreadIndex, row);
                    row.EventNodeHover    += Row_EventNodeHover;
                    row.EventNodeSelected += Row_EventNodeSelected;
                }

                if (GenerateSamplingThreads && data.Callstacks != null && data.Callstacks.Count > 3)
                {
                    ThreadData      samplingData = GenerateSamplingThread(group, data);
                    EventsThreadRow row          = new EventsThreadRow(group, new ThreadDescription()
                    {
                        Name = thread.Name + " [Sampling]", Origin = ThreadDescription.Source.Sampling
                    }, samplingData, Settings);
                    eventThreads.Add(row);
                    row.EventNodeHover    += Row_EventNodeHover;
                    row.EventNodeSelected += Row_EventNodeSelected;
                }
            }

            return(SortRows(eventThreads));
        }
        public override void OnMouseHover(Point point, ThreadScroll scroll, List <object> dataContext)
        {
            EventNode  node  = null;
            EventFrame frame = null;

            ITick tick = scroll.PixelToTime(point.X);

            if (FindNode(point, scroll, out frame, out node) != -1)
            {
                dataContext.Add(node);
            }

            // show current sync info
            if (EventData.Sync != null && EventData.Sync != null)
            {
                int index = Data.Utils.BinarySearchClosestIndex(EventData.Sync, tick.Start);
                if (index != -1)
                {
                    bool         insideWaitInterval = false;
                    WaitInterval interval           = new WaitInterval()
                    {
                        Start = EventData.Sync[index].Finish, Reason = EventData.Sync[index].Reason
                    };
                    if (index + 1 < EventData.Sync.Count)
                    {
                        if (EventData.Sync[index].Finish < tick.Start && tick.Start < EventData.Sync[index + 1].Start)
                        {
                            UInt64 threadId = EventData.Sync[index].NewThreadId;

                            ThreadDescription threadDesc = null;
                            Group.Board.ThreadDescriptions.TryGetValue(threadId, out threadDesc);

                            interval.newThreadDesc = threadDesc;
                            interval.newThreadId   = threadId;

                            interval.Finish = EventData.Sync[index + 1].Start;
                            dataContext.Add(interval);
                            insideWaitInterval = true;
                        }
                    }

                    if (!insideWaitInterval)
                    {
                        interval.Reason = SyncReason.SyncReasonActive;
                        interval.Start  = EventData.Sync[index].Start;
                        interval.Finish = EventData.Sync[index].Finish;
                        interval.core   = (byte)EventData.Sync[index].Core;
                        dataContext.Add(interval);
                    }
                }
            }

            if (node != null)
            {
                // build all intervals inside selected node
                int from = Data.Utils.BinarySearchClosestIndex(frame.Synchronization, node.Entry.Start);
                int to   = Data.Utils.BinarySearchClosestIndex(frame.Synchronization, node.Entry.Finish);

                if (from >= 0 && to >= from)
                {
                    IntPair[] waitInfo = new IntPair[(int)SyncReason.SyncReasonCount];

                    for (int index = from; index <= to; ++index)
                    {
                        SyncReason reason      = frame.Synchronization[index].Reason;
                        int        reasonIndex = (int)reason;

                        long idleStart  = frame.Synchronization[index].Finish;
                        long idleFinish = (index + 1 < frame.Synchronization.Count) ? frame.Synchronization[index + 1].Start : frame.Finish;

                        if (idleStart > node.Entry.Finish)
                        {
                            continue;
                        }

                        long idleStartClamped  = Math.Max(idleStart, node.Entry.Start);
                        long idleFinishClamped = Math.Min(idleFinish, node.Entry.Finish);
                        long durationInTicks   = idleFinishClamped - idleStartClamped;
                        waitInfo[reasonIndex].duration += durationInTicks;
                        waitInfo[reasonIndex].count++;
                    }

                    NodeWaitIntervalList intervals = new NodeWaitIntervalList();

                    for (int i = 0; i < waitInfo.Length; i++)
                    {
                        if (waitInfo[i].count > 0)
                        {
                            NodeWaitInterval interval = new NodeWaitInterval()
                            {
                                Start = 0, Finish = waitInfo[i].duration, Reason = (SyncReason)i, NodeInterval = node.Entry, Count = waitInfo[i].count
                            };
                            intervals.Add(interval);
                        }
                    }

                    intervals.Sort((a, b) =>
                    {
                        return(Comparer <long> .Default.Compare(b.Finish, a.Finish));
                    });

                    if (intervals.Count > 0)
                    {
                        dataContext.Add(intervals);
                    }
                }
            }             // FindNode

            if (EventData.Callstacks != null && scroll.DrawCallstacks != 0)
            {
                int startIndex = Data.Utils.BinarySearchClosestIndex(EventData.Callstacks, tick.Start);

                for (int i = startIndex; (i <= startIndex + 1) && (i < EventData.Callstacks.Count) && (i != -1); ++i)
                {
                    double pixelPos = scroll.TimeToPixel(EventData.Callstacks[i]);
                    if (Math.Abs(pixelPos - point.X) < CallstackMarkerRadius * 1.2 && (EventData.Callstacks[i].Reason & scroll.DrawCallstacks) != 0)
                    {
                        dataContext.Add(EventData.Callstacks[i]);
                        break;
                    }
                }
            }
        }
Exemple #6
0
        void InitThreadList(FrameGroup group)
        {
            rows.Clear();
            id2row.Clear();

            ThreadList.RowDefinitions.Clear();
            ThreadList.Children.Clear();

            if (group == null)
            {
                return;
            }

            rows.Add(new HeaderThreadRow(group)
            {
                GradientTop    = (BroAlternativeBackground as SolidColorBrush).Color,
                GradientBottom = (BroBackground as SolidColorBrush).Color,
                SplitLines     = (BroBackground as SolidColorBrush).Color,
                TextColor      = Colors.Gray
            });

            for (int i = 0; i < Math.Min(group.Board.Threads.Count, group.Threads.Count); ++i)
            {
                ThreadDescription thread = group.Board.Threads[i];
                ThreadData        data   = group.Threads[i];

                bool threadHasData = false;
                if ((data.Callstacks != null && data.Callstacks.Count > 3) ||
                    /*(data.Sync != null && data.Sync.Intervals.Count > 0) || */
                    (data.Events != null && data.Events.Count > 0))

                {
                    threadHasData = true;
                }

                if (threadHasData)
                {
                    EventsThreadRow row = new EventsThreadRow(group, thread, data);
                    rows.Add(row);
                    id2row.Add(i, row);

                    row.EventNodeHover    += Row_EventNodeHover;
                    row.EventNodeSelected += Row_EventNodeSelected;
                }
            }

            scroll.TimeSlice = group.Board.TimeSlice;
            scroll.Height    = 0.0;
            scroll.Width     = surface.ActualWidth * RenderSettings.dpiScaleX;
            rows.ForEach(row => scroll.Height += row.Height);

            rows.ForEach(row => row.BuildMesh(surface, scroll));

            ThreadList.Margin = new Thickness(0, 0, 3, 0);

            double offset = 0.0;

            for (int threadIndex = 0; threadIndex < rows.Count; ++threadIndex)
            {
                ThreadRow row = rows[threadIndex];
                row.Offset = offset;

                ThreadList.RowDefinitions.Add(new RowDefinition());

                Thickness margin = new Thickness(0, 0, 0, 0);

                Label labelName = new Label()
                {
                    Content = row.Name, Margin = margin, Padding = new Thickness(), FontWeight = FontWeights.Bold, Height = row.Height / RenderSettings.dpiScaleY, VerticalContentAlignment = VerticalAlignment.Center
                };

                Grid.SetRow(labelName, threadIndex);

                if (threadIndex % 2 == 1)
                {
                    labelName.Background = BroAlternativeBackground;
                }

                ThreadList.Children.Add(labelName);
                offset += row.Height;
            }

            InitBackgroundMesh();
        }
Exemple #7
0
        public EventsThreadRow(FrameGroup group, ThreadDescription desc, ThreadData data)
        {
            Description = desc;
            EventData   = data;
            Group       = group;
            MaxDepth    = 1;

            List <EventNode> rootCategories = new List <EventNode>();
            List <EventNode> nodesToProcess = new List <EventNode>();

            foreach (EventFrame frame in data.Events)
            {
                // Fill holes in timeline from regular events (not categories)
                // ------------------------------------------------------------------------------------------------------
                const double thresholdMs = 0.1;

                EventTree categoriesTree = frame.CategoriesTree;
                rootCategories.Clear();
                foreach (EventNode node in frame.CategoriesTree.Children)
                {
                    rootCategories.Add(node);
                }

                if (rootCategories.Count != 0)
                {
                    nodesToProcess.Clear();
                    foreach (EventNode node in frame.Root.Children)
                    {
                        nodesToProcess.Add(node);
                    }

                    while (nodesToProcess.Count > 0)
                    {
                        EventNode node = nodesToProcess[0];
                        nodesToProcess.RemoveAt(0);

                        bool nodeIntersectWithCategories = false;

                        foreach (EventNode categoryNode in rootCategories)
                        {
                            // drop nodes less than thresholdMs ms
                            if (node.Entry.Duration < thresholdMs)
                            {
                                nodeIntersectWithCategories = true;
                                break;
                            }

                            // node is entirely inside the categoryNode
                            if (node.Entry.Start >= categoryNode.Entry.Start && node.Entry.Finish <= categoryNode.Entry.Finish)
                            {
                                nodeIntersectWithCategories = true;
                                break;
                            }

                            // node is partially inside the categoryNode
                            if (node.Entry.Intersect(categoryNode.Entry))
                            {
                                foreach (EventNode tmp in node.Children)
                                {
                                    nodesToProcess.Add(tmp);
                                }

                                nodeIntersectWithCategories = true;
                                break;
                            }
                        }

                        if (nodeIntersectWithCategories == false && node.Entry.Duration >= thresholdMs)
                        {
                            // node is not intersect with any categoryNode (add to category tree)
                            EventNode fakeCategoryNode = new EventNode(frame.CategoriesTree, node.Entry);

                            node.Entry.SetOverrideColor(GenerateColorFromString(node.Entry.Description.FullName));

                            rootCategories.Add(fakeCategoryNode);
                            frame.CategoriesTree.Children.Add(fakeCategoryNode);
                        }
                    }
                }
                // ------------------------------------------------------------------------------------------------------

                MaxDepth = Math.Max(frame.CategoriesTree.Depth, MaxDepth);
            }
        }