int GetItemIdFromRawFrameDataIndexPath(HierarchyFrameDataView m_FrameDataView, List <int> deepestRawSampleIndexPathFound, out int foundDepth, out bool selectedItemsPathIsExpanded)
        {
            selectedItemsPathIsExpanded = true;
            var newSelectedId = m_FrameDataView.GetRootItemID();
            var deepestPath   = deepestRawSampleIndexPathFound.Count;

            for (int markerDepth = 0; markerDepth < deepestPath; markerDepth++)
            {
                var oldSelectedId = newSelectedId;

                if (m_FrameDataView.HasItemChildren(newSelectedId))
                {
                    // TODO: maybe HierarchyFrameDataView should just have a method GetChildItemByRawFrameDataViewIndex to avoid this List<int> marshalling need...
                    m_FrameDataView.GetItemChildren(newSelectedId, m_ReusableChildrenIds);

                    for (int i = 0; i < m_ReusableChildrenIds.Count; i++)
                    {
                        var childId = m_ReusableChildrenIds[i];

                        if (m_FrameDataView.ItemContainsRawFrameDataViewIndex(childId, deepestRawSampleIndexPathFound[markerDepth]))
                        {
                            // check if the parent is expanded
                            if (selectedItemsPathIsExpanded && !IsExpanded(newSelectedId))
                            {
                                selectedItemsPathIsExpanded = false;
                            }

                            newSelectedId = childId;
                            break;
                        }
                    }
                }
                if (oldSelectedId == newSelectedId)
                {
                    // there was no fitting sample in this scope so the path has been cut short here
                    deepestPath = markerDepth;
                    break;
                }
            }
            foundDepth = deepestPath;
            return(newSelectedId);
        }
        internal float UpdateData(HierarchyFrameDataView frameDataView, int selectedMarkerId)
        {
            totalSelectedPropertyTime = 0;

            m_Callers.Clear();
            m_Callees.Clear();

            m_ChildrenIds.Clear();
            m_Stack.Clear();
            m_Stack.Push(frameDataView.GetRootItemID());

            while (m_Stack.Count > 0)
            {
                var current = m_Stack.Pop();

                if (!frameDataView.HasItemChildren(current))
                {
                    continue;
                }

                var markerId = frameDataView.GetItemMarkerID(current);
                frameDataView.GetItemChildren(current, m_ChildrenIds);
                foreach (var childId in m_ChildrenIds)
                {
                    var childMarkerId = frameDataView.GetItemMarkerID(childId);
                    if (childMarkerId == selectedMarkerId)
                    {
                        var totalSelfTime = frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnTotalTime);
                        totalSelectedPropertyTime += totalSelfTime;

                        if (current != 0)
                        {
                            // Add markerId to callers (except root)
                            CallInformation callInfo;
                            var             totalTime = frameDataView.GetItemColumnDataAsSingle(current, HierarchyFrameDataView.columnTotalTime);
                            var             calls     = (int)frameDataView.GetItemColumnDataAsSingle(current, HierarchyFrameDataView.columnCalls);
                            var             gcAlloc   = (int)frameDataView.GetItemColumnDataAsSingle(current, HierarchyFrameDataView.columnGcMemory);
                            if (!m_Callers.TryGetValue(markerId, out callInfo))
                            {
                                m_Callers.Add(markerId, new CallInformation()
                                {
                                    id              = current,
                                    name            = frameDataView.GetItemName(current),
                                    callsCount      = calls,
                                    gcAllocBytes    = gcAlloc,
                                    totalCallTimeMs = totalTime,
                                    totalSelfTimeMs = totalSelfTime
                                });
                            }
                            else
                            {
                                callInfo.callsCount      += calls;
                                callInfo.gcAllocBytes    += gcAlloc;
                                callInfo.totalCallTimeMs += totalTime;
                                callInfo.totalSelfTimeMs += totalSelfTime;
                            }
                        }
                    }

                    if (markerId == selectedMarkerId)
                    {
                        // Add childMarkerId to callees
                        CallInformation callInfo;
                        var             totalTime = frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnTotalTime);
                        var             calls     = (int)frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnCalls);
                        var             gcAlloc   = (int)frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnGcMemory);
                        if (!m_Callees.TryGetValue(childMarkerId, out callInfo))
                        {
                            m_Callees.Add(childMarkerId, new CallInformation()
                            {
                                id              = childId,
                                name            = frameDataView.GetItemName(childId),
                                callsCount      = calls,
                                gcAllocBytes    = gcAlloc,
                                totalCallTimeMs = totalTime,
                                totalSelfTimeMs = 0
                            });
                        }
                        else
                        {
                            callInfo.callsCount      += calls;
                            callInfo.gcAllocBytes    += gcAlloc;
                            callInfo.totalCallTimeMs += totalTime;
                        }
                    }

                    m_Stack.Push(childId);
                }
            }
            UpdateCallsData(ref m_CallersData, m_Callers, totalSelectedPropertyTime);
            UpdateCallsData(ref m_CalleesData, m_Callees, totalSelectedPropertyTime);
            return(totalSelectedPropertyTime);
        }
Пример #3
0
        void MigrateSelectedState(bool expandIfNecessary)
        {
            if (m_SelectedItemMarkerIdPath == null && m_LegacySelectedItemMarkerNamePath == null)
            {
                return;
            }

            // Find view id which corresponds to markerPath
            var  newSelectedId = m_FrameDataView.GetRootItemID();
            bool selectedItemsPathIsExpanded = true;

            if (m_SelectedItemMarkerIdPath != null)
            {
                foreach (var marker in m_SelectedItemMarkerIdPath)
                {
                    if (m_FrameDataView.HasItemChildren(newSelectedId))
                    {
                        m_FrameDataView.GetItemChildren(newSelectedId, m_ReusableChildrenIds);
                        foreach (var childId in m_ReusableChildrenIds)
                        {
                            if (marker == m_FrameDataView.GetItemMarkerID(childId))
                            {
                                // check if the parent is expanded
                                if (!IsExpanded(newSelectedId))
                                {
                                    selectedItemsPathIsExpanded = false;
                                }

                                newSelectedId = childId;
                                break;
                            }
                        }
                    }

                    if (newSelectedId == 0)
                    {
                        break;
                    }
                }
            }
            else if (m_LegacySelectedItemMarkerNamePath != null)
            {
                var markerIdPath = new List <int>();
                var markerNames  = m_LegacySelectedItemMarkerNamePath.Split('/');
                foreach (var markerName in markerNames)
                {
                    if (m_FrameDataView.HasItemChildren(newSelectedId))
                    {
                        m_FrameDataView.GetItemChildren(newSelectedId, m_ReusableChildrenIds);
                        foreach (var childId in m_ReusableChildrenIds)
                        {
                            if (markerName == m_FrameDataView.GetItemName(childId))
                            {
                                // check if the parent is expanded
                                if (!IsExpanded(newSelectedId))
                                {
                                    selectedItemsPathIsExpanded = false;
                                }

                                newSelectedId = childId;
                                markerIdPath.Add(m_FrameDataView.GetItemMarkerID(childId));
                                break;
                            }
                        }
                    }

                    if (newSelectedId == 0)
                    {
                        break;
                    }
                }

                m_SelectedItemMarkerIdPath         = markerIdPath;
                m_LegacySelectedItemMarkerNamePath = null;
            }

            var newSelection = (newSelectedId == 0) ? new List <int>() : new List <int>()
            {
                newSelectedId
            };

            state.selectedIDs = newSelection;

            // Framing invalidates expanded state and this is very expensive operation to perform each frame.
            // Thus we auto frame selection only when we are not profiling.
            var collectingSamples = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying);
            var isFramingAllowed  = !collectingSamples;

            if (newSelectedId != 0 && isInitialized && isFramingAllowed && (selectedItemsPathIsExpanded || expandIfNecessary))
            {
                FrameItem(newSelectedId);
            }
        }
        internal void UpdateData(HierarchyFrameDataView frameDataView, int selectedMarkerId)
        {
            totalSelectedPropertyTime = 0;

            m_Callers.Clear();
            m_Callees.Clear();

            m_ChildrenIds.Clear();
            m_Stack.Clear();
            m_Stack.Push(frameDataView.GetRootItemID());

            while (m_Stack.Count > 0)
            {
                var current = m_Stack.Pop();

                if (!frameDataView.HasItemChildren(current))
                {
                    continue;
                }

                var markerId = frameDataView.GetItemMarkerID(current);
                frameDataView.GetItemChildren(current, m_ChildrenIds);
                foreach (var childId in m_ChildrenIds)
                {
                    var childMarkerId = frameDataView.GetItemMarkerID(childId);
                    if (childMarkerId == selectedMarkerId)
                    {
                        var totalSelfTime = frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnTotalTime);
                        totalSelectedPropertyTime += totalSelfTime;

                        // Skip root sample
                        if (current != 0)
                        {
                            // Add markerId to callers (except root)
                            CallInformation callInfo;
                            var             totalTime = frameDataView.GetItemColumnDataAsSingle(current, HierarchyFrameDataView.columnTotalTime);
                            // Display sample details in the scope of caller.
                            var calls   = (int)frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnCalls);
                            var gcAlloc = (int)frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnGcMemory);
                            if (!m_Callers.TryGetValue(markerId, out callInfo))
                            {
                                m_Callers.Add(markerId, new CallInformation()
                                {
                                    id              = current,
                                    name            = profilerSampleNameProvider.GetItemName(frameDataView, current),
                                    callsCount      = calls,
                                    gcAllocBytes    = gcAlloc,
                                    totalCallTimeMs = totalTime,
                                    totalSelfTimeMs = totalSelfTime
                                });
                            }
                            else
                            {
                                callInfo.callsCount += calls;
                                // Ignore adding time and gc allocations for recursive like calls
                                if (markerId != childMarkerId)
                                {
                                    callInfo.gcAllocBytes    += gcAlloc;
                                    callInfo.totalCallTimeMs += totalTime;
                                    callInfo.totalSelfTimeMs += totalSelfTime;
                                }
                            }
                        }
                    }

                    if (markerId == selectedMarkerId)
                    {
                        // Add childMarkerId to callees
                        CallInformation callInfo;
                        var             totalTime = frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnTotalTime);
                        var             calls     = (int)frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnCalls);
                        var             gcAlloc   = (int)frameDataView.GetItemColumnDataAsSingle(childId, HierarchyFrameDataView.columnGcMemory);
                        if (!m_Callees.TryGetValue(childMarkerId, out callInfo))
                        {
                            m_Callees.Add(childMarkerId, new CallInformation()
                            {
                                id              = childId,
                                name            = profilerSampleNameProvider.GetItemName(frameDataView, childId),
                                callsCount      = calls,
                                gcAllocBytes    = gcAlloc,
                                totalCallTimeMs = totalTime,
                                totalSelfTimeMs = 0
                            });
                        }
                        else
                        {
                            callInfo.callsCount += calls;
                            // Ignore adding time and gc allocations for recursive like calls
                            if (markerId != childMarkerId)
                            {
                                callInfo.gcAllocBytes    += gcAlloc;
                                callInfo.totalCallTimeMs += totalTime;
                            }
                        }
                    }

                    m_Stack.Push(childId);
                }
            }
            UpdateCallsData(ref m_CallersData, m_Callers, totalSelectedPropertyTime);
            UpdateCallsData(ref m_CalleesData, m_Callees, totalSelectedPropertyTime);
        }
        void MigrateSelectedState(bool expandIfNecessary, bool framingAllowed)
        {
            if (m_LocalSelectedItemMarkerIdPath == null || m_Selected == null || m_LocalSelectedItemMarkerIdPath.Count != m_Selected.markerNamePath.Count)
            {
                return;
            }

            m_SelectionNeedsMigration = false;

            var markerNamePath = m_Selected.markerNamePath;

            expandIfNecessary |= m_ExpandDuringNextSelectionMigration;

            using (k_MigrateSelectionStateMarker.Auto())
            {
                var safeFrameWithSafeMarkerIds = m_Selected.frameIndexIsSafe && m_FrameDataView.frameIndex == m_Selected.safeFrameIndex;
                var rawHierarchyView           = (m_FrameDataView.viewMode & HierarchyFrameDataView.ViewModes.MergeSamplesWithTheSameName) == HierarchyFrameDataView.ViewModes.Default;
                var allowProxySelection        = !safeFrameWithSafeMarkerIds;

                var finalRawSampleIndex = RawFrameDataView.invalidSampleIndex;

                using (var frameData = new RawFrameDataView(m_FrameDataView.frameIndex, m_FrameDataView.threadIndex))
                {
                    if (!frameData.valid)
                    {
                        return;
                    }
                    if (!safeFrameWithSafeMarkerIds)
                    {
                        // marker names might have changed Ids between frames, update them if that is the case
                        for (int i = 0; i < m_LocalSelectedItemMarkerIdPath.Count; i++)
                        {
                            m_LocalSelectedItemMarkerIdPath[i] = frameData.GetMarkerId(markerNamePath[i]);
                        }
                    }
                    else if (!allowProxySelection)
                    {
                        for (int i = 0; i < m_LocalSelectedItemMarkerIdPath.Count; i++)
                        {
                            var markerIsEditorOnlyMarker = frameData.GetMarkerFlags(m_LocalSelectedItemMarkerIdPath[i]).HasFlag(Unity.Profiling.LowLevel.MarkerFlags.AvailabilityEditor);
                            if (markerIsEditorOnlyMarker && i < m_LocalSelectedItemMarkerIdPath.Count - 1)
                            {
                                // Technically, proxy selections are not supposed to be allowed when switching between views in the same frame.
                                // However, if there are Editor Only markers in the path that are NOT the last item, Hierarchy View might have collapsed the path from this point forward,
                                // so we need to allow Proxy Selections here.
                                allowProxySelection = true;
                                break;
                            }
                        }
                    }
                    var name = m_Selected.sampleDisplayName;
                    m_CachedDeepestRawSampleIndexPath.Clear();
                    if (m_CachedDeepestRawSampleIndexPath.Capacity < markerNamePath.Count)
                    {
                        m_CachedDeepestRawSampleIndexPath.Capacity = markerNamePath.Count;
                    }

                    if (allowProxySelection || rawHierarchyView)
                    {
                        finalRawSampleIndex = ProfilerTimelineGUI.FindFirstSampleThroughMarkerPath(
                            frameData, m_ProfilerSampleNameProvider,
                            m_LocalSelectedItemMarkerIdPath, markerNamePath.Count, ref name,
                            longestMatchingPath: m_CachedDeepestRawSampleIndexPath);
                    }
                    else
                    {
                        finalRawSampleIndex = ProfilerTimelineGUI.FindNextSampleThroughMarkerPath(
                            frameData, m_ProfilerSampleNameProvider,
                            m_LocalSelectedItemMarkerIdPath, markerNamePath.Count, ref name,
                            ref m_CachedDeepestRawSampleIndexPath);
                    }
                }
                var  newSelectedId = m_FrameDataView.GetRootItemID();
                bool selectedItemsPathIsExpanded = true;
                var  proxySelection = new ProxySelection();
                proxySelectionInfo = default;
                var deepestPath = m_CachedDeepestRawSampleIndexPath.Count;

                if (finalRawSampleIndex >= 0 || allowProxySelection && deepestPath > 0)
                {
                    // if a valid raw index was found, find the corresponding HierarchyView Sample id next:
                    newSelectedId = GetItemIdFromRawFrameDataIndexPath(m_FrameDataView, m_CachedDeepestRawSampleIndexPath, out deepestPath, out selectedItemsPathIsExpanded);
                    if (m_LocalSelectedItemMarkerIdPath.Count > deepestPath && newSelectedId >= 0)
                    {
                        proxySelection.hasProxySelection            = true;
                        proxySelection.nonProxyName                 = m_Selected.sampleDisplayName;
                        proxySelection.nonProxySampleStack          = m_Selected.markerNamePath;
                        proxySelection.pathLengthDifferenceForProxy = deepestPath - m_LocalSelectedItemMarkerIdPath.Count;
                    }
                }

                var newSelection = (newSelectedId == 0) ? new List <int>() : new List <int>()
                {
                    newSelectedId
                };
                state.selectedIDs = newSelection;

                // Framing invalidates expanded state and this is very expensive operation to perform each frame.
                // Thus we auto frame selection only when we are not currently receiving profiler data from the Editor we are profiling, or the user opted into a "Live" view of the data
                if (newSelectedId != 0 && isInitialized && framingAllowed && (selectedItemsPathIsExpanded || expandIfNecessary))
                {
                    FrameItem(newSelectedId);
                }
                m_ExpandDuringNextSelectionMigration = false;

                proxySelectionInfo = proxySelection;
            }
        }