Example #1
0
        public void QuickScan()
        {
            var frameData = new ProfilerFrameDataIterator();

            m_threadNames.Clear();
            int frameIndex  = 0;
            int threadCount = frameData.GetThreadCount(0);

            frameData.SetRoot(frameIndex, 0);

            Dictionary <string, int> threadNameCount = new Dictionary <string, int>();

            for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
            {
                frameData.SetRoot(frameIndex, threadIndex);

                var threadName = frameData.GetThreadName();
                if (!threadNameCount.ContainsKey(threadName))
                {
                    threadNameCount.Add(threadName, 1);
                }
                else
                {
                    threadNameCount[threadName] += 1;
                }
                m_threadNames.Add(ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName));
            }

            frameData.Dispose();
        }
Example #2
0
        private ProfileData GetData(ProfilerFrameDataIterator frameData, int firstFrameIndex, int lastFrameIndex)
        {
            var data = new ProfileData();

            data.SetFrameIndexOffset(firstFrameIndex);

            Dictionary <string, int> threadNameCount = new Dictionary <string, int>();

            for (int frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; ++frameIndex)
            {
                m_progressBar.AdvanceProgressBar();

                int threadCount = frameData.GetThreadCount(frameIndex);
                frameData.SetRoot(frameIndex, 0);

                var msFrame = frameData.frameTimeMS;

                ProfileFrame frame = new ProfileFrame();
                frame.msFrame = msFrame;
                data.Add(frame);

                threadNameCount.Clear();
                for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
                {
                    frameData.SetRoot(frameIndex, threadIndex);

                    var threadName = frameData.GetThreadName();
                    if (threadName.Trim() == "")
                    {
                        Debug.Log(string.Format("Warning: Unnamed thread found on frame {0}. Corrupted data suspected, ignoring frame", frameIndex));
                        continue;
                    }

                    ProfileThread thread = new ProfileThread();
                    frame.Add(thread);

                    if (!threadNameCount.ContainsKey(threadName))
                    {
                        threadNameCount.Add(threadName, 1);
                    }
                    else
                    {
                        threadNameCount[threadName] += 1;
                    }
                    data.AddThreadName(ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName), thread);

                    const bool enterChildren = true;
                    while (frameData.Next(enterChildren))
                    {
                        var ms         = frameData.durationMS;
                        var markerData = ProfileMarker.Create(frameData);
                        thread.Add(markerData);
                        data.AddMarkerName(frameData.name, markerData);
                    }
                }
            }

            return(data);
        }
Example #3
0
        public ProfileData GrabFromProfiler(int firstFrameDisplayIndex, int lastFrameDisplayIndex)
        {
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
            int         firstFrameIndex         = firstFrameDisplayIndex - 1;
            int         lastFrameIndex          = lastFrameDisplayIndex - 1;
            ProfileData profileData             = GetData(frameData, firstFrameIndex, lastFrameIndex);

            frameData.Dispose();
            return(profileData);
        }
Example #4
0
        public static ProfileMarker Create(ProfilerFrameDataIterator frameData)
        {
            var item = new ProfileMarker
            {
                msFrame = frameData.durationMS,
                depth   = frameData.depth
            };

            return(item);
        }
Example #5
0
        public float GetFrameTime(int frameIndex)
        {
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();

            frameData.SetRoot(frameIndex, 0);
            float ms = frameData.frameTimeMS;

            frameData.Dispose();

            return(ms);
        }
        private bool GetMarkerInfo(string markerName, int frameIndex, string threadFilter, out int outThreadIndex, out float time, out float duration, out int instanceId)
        {
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();

            outThreadIndex = 0;
            time           = 0.0f;
            duration       = 0.0f;
            instanceId     = 0;
            bool found = false;

            int threadCount = frameData.GetThreadCount(frameIndex);
            Dictionary <string, int> threadNameCount = new Dictionary <string, int>();

            for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
            {
                frameData.SetRoot(frameIndex, threadIndex);

                var threadName = frameData.GetThreadName();
                if (!threadNameCount.ContainsKey(threadName))
                {
                    threadNameCount.Add(threadName, 1);
                }
                else
                {
                    threadNameCount[threadName] += 1;
                }
                var threadNameWithIndex = ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName);

                if (threadFilter == "All" || threadNameWithIndex == threadFilter)
                {
                    const bool enterChildren = true;
                    while (frameData.Next(enterChildren))
                    {
                        if (frameData.name == markerName)
                        {
                            time           = frameData.startTimeMS;
                            duration       = frameData.durationMS;
                            instanceId     = frameData.instanceId;
                            outThreadIndex = threadIndex;
                            found          = true;
                            break;
                        }
                    }
                }

                if (found)
                {
                    break;
                }
            }

            frameData.Dispose();
            return(found);
        }
        public static ProfileMarker Create(ProfilerFrameDataIterator frameData)
        {
            var item = new ProfileMarker
            {
                msMarkerTotal = frameData.durationMS,
                depth         = frameData.depth,
                msChildren    = 0.0f
            };

            return(item);
        }
Example #8
0
        public ProfileData PullFromProfiler(int firstFrameDisplayIndex, int lastFrameDisplayIndex)
        {
            Profiler.BeginSample("ProfileAnalyzer.PullFromProfiler");
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
            int         firstFrameIndex         = firstFrameDisplayIndex - 1;
            int         lastFrameIndex          = lastFrameDisplayIndex - 1;
            ProfileData profileData             = GetData(frameData, firstFrameIndex, lastFrameIndex);

            frameData.Dispose();
            Profiler.EndSample();
            return(profileData);
        }
Example #9
0
        public int GetThreadCountForFrame(int frameIndex)
        {
            if (!IsReady())
            {
                return(0);
            }

            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();

            frameData.SetRoot(frameIndex, 0);
            return(frameData.GetThreadCount(frameIndex));
        }
        private void DrawThreadPopup(HierarchyFrameDataView frameDataView)
        {
            if (!frameDataView.valid)
            {
                var disabledValues = new string[] { m_ThreadName };
                EditorGUILayout.AdvancedPopup(0, disabledValues, BaseStyles.detailedViewTypeToolbarDropDown, GUILayout.Width(BaseStyles.detailedViewTypeToolbarDropDown.fixedWidth));
                return;
            }

            if (m_FrameIndex != frameDataView.frameIndex)
            {
                m_FrameIndex  = frameDataView.frameIndex;
                m_ThreadIndex = 0;

                using (var frameIterator = new ProfilerFrameDataIterator())
                {
                    var threadCount = frameIterator.GetThreadCount(m_FrameIndex);
                    m_ThreadNames   = new string[threadCount];
                    m_ThreadIndices = new int[threadCount];
                    for (var i = 0; i < threadCount; ++i)
                    {
                        frameIterator.SetRoot(m_FrameIndex, i);
                        var groupName  = frameIterator.GetGroupName();
                        var threadName = frameIterator.GetThreadName();
                        var name       = string.IsNullOrEmpty(groupName) ? threadName : groupName + "." + threadName;
                        m_ThreadNames[i]   = name;
                        m_ThreadIndices[i] = i;
                        if (m_ThreadName == name)
                        {
                            m_ThreadIndex = i;
                        }
                    }

                    Array.Sort(m_ThreadNames, m_ThreadIndices, new ThreadComparer());
                    for (var i = 0; i < threadCount; ++i)
                    {
                        if (m_ThreadName == m_ThreadNames[i])
                        {
                            m_ThreadIndex = i;
                        }
                    }
                }
            }

            var newThreadIndex = EditorGUILayout.AdvancedPopup(m_ThreadIndex, m_ThreadNames, BaseStyles.detailedViewTypeToolbarDropDown, GUILayout.Width(BaseStyles.detailedViewTypeToolbarDropDown.fixedWidth));

            if (newThreadIndex != m_ThreadIndex)
            {
                m_ThreadIndex = newThreadIndex;
                m_ThreadName  = m_ThreadNames[m_ThreadIndex];
            }
        }
        void UpdateThreadNamesAndThreadIndex(HierarchyFrameDataView frameDataView)
        {
            if (m_FrameIndex == frameDataView.frameIndex)
            {
                return;
            }

            m_FrameIndex = frameDataView.frameIndex;
            threadIndex  = 0;

            using (var frameIterator = new ProfilerFrameDataIterator())
            {
                var threadCount = frameIterator.GetThreadCount(m_FrameIndex);
                if (m_ThreadInfoCache == null || m_ThreadInfoCache.Capacity < threadCount)
                {
                    m_ThreadInfoCache = new List <ThreadInfo>(threadCount);
                }
                m_ThreadInfoCache.Clear();

                // Fetch all thread names
                for (var i = 0; i < threadCount; ++i)
                {
                    frameIterator.SetRoot(m_FrameIndex, i);
                    var groupName  = frameIterator.GetGroupName();
                    var threadName = frameIterator.GetThreadName();
                    var name       = string.IsNullOrEmpty(groupName) ? threadName : groupName + "." + threadName;
                    m_ThreadInfoCache.Add(new ThreadInfo()
                    {
                        groupOrder = GetGroupOrder(name), fullName = name
                    });
                }

                m_ThreadInfoCache.Sort();

                if (m_ThreadNames == null || m_ThreadNames.Length != threadCount)
                {
                    m_ThreadNames = new string[threadCount];
                }
                // Make a display list with a current index selected
                for (var i = 0; i < threadCount; ++i)
                {
                    m_ThreadNames[i] = m_ThreadInfoCache[i].fullName;
                    if (m_ThreadName == m_ThreadNames[i])
                    {
                        threadIndex = i;
                    }
                }
            }
        }
Example #12
0
        public float GetFrameTime(int frameIndex)
        {
#if UNITY_2020_1_OR_NEWER
            if (s_UseRawIterator)
            {
                return(GetFrameTimeRaw(frameIndex));
            }
#endif
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();

            frameData.SetRoot(frameIndex, 0);
            float ms = frameData.frameTimeMS;
            frameData.Dispose();

            return(ms);
        }
Example #13
0
        internal static int GetThreadIndex(int frameIndex, string threadGroupName, string threadName, ulong threadId)
        {
            if (frameIndex > ProfilerDriver.lastFrameIndex || frameIndex < ProfilerDriver.firstFrameIndex)
            {
                return(FrameDataView.invalidThreadIndex);
            }
            if (string.IsNullOrEmpty(threadGroupName))
            {
                threadGroupName = string.Empty;
            }
            var foundIndex = FrameDataView.invalidThreadIndex;

            using (var frameDataIterator = new ProfilerFrameDataIterator())
            {
                var threadCount = frameDataIterator.GetThreadCount(frameIndex);
                for (int i = 0; i < threadCount; i++)
                {
                    using (var frameData = ProfilerDriver.GetRawFrameDataView(frameIndex, i))
                    {
                        // only string compare if both names aren't null or empty, i.e. don't compare ` null != "" ` but treat null the same as empty
                        if (((string.IsNullOrEmpty(frameData.threadGroupName) && string.IsNullOrEmpty(threadGroupName)) || frameData.threadGroupName == threadGroupName) &&
                            frameData.threadName == threadName)
                        {
                            // do we have a valid thread id to check against and a direct match?
                            if (threadId == FrameDataView.invalidThreadId || frameData.threadId == threadId)
                            {
                                return(frameData.threadIndex);
                            }
                            // else store the first found thread index as a fallback
                            else if (foundIndex == FrameDataView.invalidThreadIndex)
                            {
                                foundIndex = frameData.threadIndex;
                            }
                        }
                    }
                }
            }
            return(foundIndex);
        }
Example #14
0
        IEnumerator <ThreadIndexIterator> GetNextThreadIndexFittingThreadFilters(int frameIndex, List <string> threadFilters)
        {
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();

            int threadCount = frameData.GetThreadCount(frameIndex);
            Dictionary <string, int> threadNameCount = new Dictionary <string, int>();

            for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
            {
                frameData.SetRoot(frameIndex, threadIndex);

                var threadName = frameData.GetThreadName();
                // Name here could be "Worker Thread 1"

                var groupName = frameData.GetGroupName();
                threadName = ProfileData.GetThreadNameWithGroup(threadName, groupName);

                int nameCount = 0;
                threadNameCount.TryGetValue(threadName, out nameCount);
                threadNameCount[threadName] = nameCount + 1;

                var threadNameWithIndex = ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName);

                // To compare on the filter we need to remove the postfix on the thread name
                // "3:Worker Thread 0" -> "1:Worker Thread"
                // The index of the thread (0) is used +1 as a prefix
                // The preceding number (3) is the count of number of threads with this name
                // Unfortunately multiple threads can have the same name
                threadNameWithIndex = ProfileData.CorrectThreadName(threadNameWithIndex);

                if (threadFilters.Contains(threadNameWithIndex))
                {
                    yield return(new ThreadIndexIterator {
                        frameData = frameData, threadIndex = threadIndex
                    });
                }
            }
            frameData.Dispose();
        }
Example #15
0
 internal RawFrameDataView GetRenderThread(RawFrameDataView frameDataView)
 {
     //Find render thread
     using (ProfilerFrameDataIterator frameDataIterator = new ProfilerFrameDataIterator())
     {
         var threadCount = frameDataIterator.GetThreadCount(frameDataView.frameIndex);
         for (int i = 0; i < threadCount; ++i)
         {
             RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView(frameDataView.frameIndex, i);
             if (frameData.threadName == "Render Thread")
             {
                 return(frameData);
             }
             else
             {
                 frameData.Dispose();
             }
         }
         // If there's no render thread, metadata was pushed on main thread
         return(frameDataView);
     }
 }
        public HierarchyFrameDataView GetFrameDataView(string threadName, HierarchyFrameDataView.ViewModes viewMode, int profilerSortColumn, bool sortAscending)
        {
            var frameIndex  = GetActiveVisibleFrameIndex();
            var threadIndex = 0;

            using (var frameIterator = new ProfilerFrameDataIterator())
            {
                var threadCount = frameIterator.GetThreadCount(frameIndex);
                for (var i = 0; i < threadCount; ++i)
                {
                    frameIterator.SetRoot(frameIndex, i);
                    var grp  = frameIterator.GetGroupName();
                    var thrd = frameIterator.GetThreadName();
                    var name = string.IsNullOrEmpty(grp) ? thrd : grp + "." + thrd;
                    if (threadName == name)
                    {
                        threadIndex = i;
                        break;
                    }
                }
            }

            if (m_FrameDataView != null && m_FrameDataView.valid)
            {
                if (m_FrameDataView.frameIndex == frameIndex && m_FrameDataView.threadIndex == threadIndex && m_FrameDataView.viewMode == viewMode)
                {
                    return(m_FrameDataView);
                }
            }

            if (m_FrameDataView != null)
            {
                m_FrameDataView.Dispose();
            }

            m_FrameDataView = new HierarchyFrameDataView(frameIndex, threadIndex, viewMode, profilerSortColumn, sortAscending);
            return(m_FrameDataView);
        }
Example #17
0
        public ProfileFrame GetProfileFrameForThread(int frameIndex, int threadIndex)
        {
            if (!IsReady())
            {
                return(null);
            }

            var frame = new ProfileFrame();

#if UNITY_2020_1_OR_NEWER
            using (RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView(frameIndex, threadIndex))
            {
                frame.msStartTime = frameData.frameStartTimeMs;
                frame.msFrame     = frameData.frameTimeMs;
            }
#else
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
            frameData.SetRoot(frameIndex, threadIndex);
            frame.msStartTime = 1000.0 * frameData.GetFrameStartS(frameIndex);
            frame.msFrame     = frameData.frameTimeMS;
#endif
            return(frame);
        }
Example #18
0
        ProfileData GetDataOriginal(ProfileData data, int firstFrameIndex, int lastFrameIndex)
        {
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
            bool firstError = true;

            data.SetFrameIndexOffset(firstFrameIndex);

            Dictionary <string, int> threadNameCount = new Dictionary <string, int>();

            for (int frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; ++frameIndex)
            {
                m_progressBar.AdvanceProgressBar();

                int threadCount = frameData.GetThreadCount(frameIndex);
                frameData.SetRoot(frameIndex, 0);

                var msFrame = frameData.frameTimeMS;

                /*
                 * if (frameIndex == lastFrameIndex)
                 * {
                 *  // Check if last frame appears to be invalid data
                 *  float median;
                 *  float mean;
                 *  float standardDeviation;
                 *  CalculateFrameTimeStats(data, out median, out mean, out standardDeviation);
                 *  float execessiveDeviation = (3f * standardDeviation);
                 *  if (msFrame > (median + execessiveDeviation))
                 *  {
                 *      Debug.LogFormat("Dropping last frame as it is significantly larger than the median of the rest of the data set {0} > {1} (median {2} + 3 * standard deviation {3})", msFrame, median + execessiveDeviation, median, standardDeviation);
                 *      break;
                 *  }
                 *  if (msFrame < (median - execessiveDeviation))
                 *  {
                 *      Debug.LogFormat("Dropping last frame as it is significantly smaller than the median of the rest of the data set {0} < {1} (median {2} - 3 * standard deviation {3})", msFrame, median - execessiveDeviation, median, standardDeviation);
                 *      break;
                 *  }
                 * }
                 */

                ProfileFrame frame = new ProfileFrame();
                frame.msStartTime = 1000.0 * frameData.GetFrameStartS(frameIndex);
                frame.msFrame     = msFrame;
                data.Add(frame);

                threadNameCount.Clear();
                for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
                {
                    frameData.SetRoot(frameIndex, threadIndex);

                    var threadName = frameData.GetThreadName();
                    if (threadName.Trim() == "")
                    {
                        Debug.Log(string.Format("Warning: Unnamed thread found on frame {0}. Corrupted data suspected, ignoring frame", frameIndex));
                        continue;
                    }

                    var groupName = frameData.GetGroupName();
                    threadName = ProfileData.GetThreadNameWithGroup(threadName, groupName);

                    ProfileThread thread = new ProfileThread();
                    frame.Add(thread);

                    int nameCount = 0;
                    threadNameCount.TryGetValue(threadName, out nameCount);
                    threadNameCount[threadName] = nameCount + 1;

                    data.AddThreadName(ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName), thread);

                    const bool enterChildren = true;
                    // The markers are in depth first order and the depth is known
                    // So we can infer a parent child relationship
                    while (frameData.Next(enterChildren))
                    {
                        if (frameData.durationMS < 0)
                        {
                            if (firstError)
                            {
                                int displayIndex = data.OffsetToDisplayFrame(frameIndex);

                                Debug.LogFormat("Ignoring Invalid marker time found for {0} on frame {1} on thread {2} ({3} < 0) : Instance id : {4}",
                                                frameData.name, displayIndex, threadName, frameData.durationMS, frameData.instanceId);

                                firstError = false;
                            }
                            continue;
                        }
                        var markerData = ProfileMarker.Create(frameData);

                        data.AddMarkerName(frameData.name, markerData);
                        thread.AddMarker(markerData);
                    }
                }
            }

            data.Finalise();

            frameData.Dispose();
            return(data);
        }
Example #19
0
        public static void PullDataStatic(ref AssetCaptureData captureData, Dictionary <string, AssetMarkerInfo> markers, ref Dictionary <string, int> markerToIDMap, int firstFrameIndex, int lastFrameIndex)
        {
            string error = null;

            var depthStack = new Stack <int>();

            captureData.m_AssetLoadMarkers.Clear();
            captureData.m_StartTimeNs = ulong.MaxValue;
            captureData.m_EndTimeNs   = ulong.MinValue;

            ProfilerFrameDataIterator frameIter = new ProfilerFrameDataIterator();
            double nsFrameStart;

            for (int frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; ++frameIndex)
            {
                frameIter.SetRoot(frameIndex, 0);

                int threadCount = frameIter.GetThreadCount(frameIndex);

                // iterate over the threads
                for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
                {
                    using (RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView(frameIndex, threadIndex))
                    {
                        if (!frameData.valid)
                        {
                            break;
                        }

                        string fullThreadName = GetFullThreadName(frameData.threadGroupName, frameData.threadName);

                        nsFrameStart = frameData.frameStartTimeNs;
                        if (frameIndex == firstFrameIndex) // This may only need to be done for the main thread, but does the main thread have a guaranteed index?
                        {
                            if (captureData.m_StartTimeNs > nsFrameStart)
                            {
                                captureData.m_StartTimeNs = nsFrameStart; // We will assume that this will only be true for the first frame and thus not be changed, and proceed to use this value as the start time
                            }
                        }

                        GetMarkerIDs(frameData, markers, ref markerToIDMap);

                        depthStack.Clear();
                        // iterate over the samples to collect up any markers
                        int sampleCount = frameData.sampleCount;
                        for (int i = 0; i < sampleCount; ++i)
                        {
                            int markerId = frameData.GetSampleMarkerId(i);

                            if (markerId != FrameDataView.invalidMarkerId && markerToIDMap.ContainsValue(markerId))
                            {
                                s_AddNewMarker.Begin();
                                string markerName = frameData.GetMarkerName(markerId);
                                Assert.IsTrue(markers.ContainsKey(markerName), string.Format("Marker {0} is not present in requested markers.", markerName));

                                // if the marker isn't a continuation of a previous marker, add a new asset load marker
                                if (!CheckForContinuationMarker(frameData, ref captureData, threadIndex, markerId, frameIndex, i))
                                {
                                    AssetLoadMarker assetLoadMarker = new AssetLoadMarker();

                                    // fill in contexts from Metadata
                                    AssetMarkerInfo markerInfo = markers[markerName];
                                    if (markerInfo.metadataCount == frameData.GetSampleMetadataCount(i))
                                    {
                                        markerInfo.metaDataFiller(ref assetLoadMarker, frameData, i);
                                    }
                                    else if (string.IsNullOrEmpty(error)) // Check the error is only shown once
                                    {
                                        error = $"Some markers, such as '{markerName}', have unexpected metadata. This may be because of opening a profile captured with an older version of Unity. Certain values may be missing.";
                                        Debug.LogWarning(error);
                                    }

                                    ulong markerStartTimeNs = frameData.GetSampleStartTimeNs(i);
                                    ulong sampleLengthNs    = frameData.GetSampleTimeNs(i);

                                    assetLoadMarker.markerId = markerId;

                                    if (string.IsNullOrEmpty(assetLoadMarker.filename))
                                    {
                                        assetLoadMarker.readablePath     = "Unknown path";
                                        assetLoadMarker.readableFileName = "?";
                                    }
                                    else
                                    {
                                        assetLoadMarker.readablePath     = assetLoadMarker.filename;
                                        assetLoadMarker.readableFileName = Path.GetFileName(assetLoadMarker.readablePath);
                                        if (assetLoadMarker.readablePath.Contains("/Analytics/"))
                                        {
                                            assetLoadMarker.readableFileName += " (Analytics)";
                                        }
                                    }

                                    assetLoadMarker.startNs  = markerStartTimeNs;
                                    assetLoadMarker.lengthNs = sampleLengthNs;
                                    assetLoadMarker.endNs    = markerStartTimeNs + sampleLengthNs;

                                    assetLoadMarker.startTimeMs = (markerStartTimeNs - captureData.m_StartTimeNs) * 0.000001; // could this go negative?
                                    assetLoadMarker.ms          = assetLoadMarker.lengthNs * 0.000001;
                                    assetLoadMarker.frameCount  = 1;

                                    assetLoadMarker.type            = markerInfo.assetMarkerType;
                                    assetLoadMarker.markerName      = markerName;
                                    assetLoadMarker.threadName      = fullThreadName;
                                    assetLoadMarker.firstFrameIndex = frameIndex;
                                    assetLoadMarker.lastFrameIndex  = frameIndex;
                                    assetLoadMarker.threadIndex     = threadIndex;
                                    assetLoadMarker.threadId        = frameData.threadId;
                                    assetLoadMarker.sampleIds.Add(i);
                                    assetLoadMarker.depth = 1 + depthStack.Count;

                                    captureData.m_AssetLoadMarkers.Add(assetLoadMarker);
                                }

                                s_AddNewMarker.End();
                            }
                            UpdateDepthStack(ref depthStack, frameData.GetSampleChildrenCount(i));
                        }
                    }
                }
            }
            frameIter.Dispose();
        }
        void UpdateThreadNamesAndThreadIndex(HierarchyFrameDataView frameDataView, bool forceUpdate = false)
        {
            if (frameDataView == null || !frameDataView.valid || (m_FrameIndex == frameDataView.frameIndex && !forceUpdate && m_ThreadInfoCache != null))
            {
                // make sure these caches and the selection have somewhat valid data
                if (m_ThreadInfoCache == null || m_ThreadInfoCache.Count <= 0)
                {
                    m_ThreadInfoCache = new List <ThreadInfo>();
                    m_ThreadInfoCache.Add(CreateThreadInfoForCurrentlyShownThread());
                }
                if (threadIndexInThreadNames < 0 || threadIndexInThreadNames > m_ThreadInfoCache.Count)
                {
                    threadIndexInThreadNames = 0;
                }
                return;
            }

            m_FrameIndex             = frameDataView.frameIndex;
            threadIndexInThreadNames = FrameDataView.invalidThreadIndex;

            using (var frameIterator = new ProfilerFrameDataIterator())
            {
                var threadCount = frameIterator.GetThreadCount(m_FrameIndex);
                if (m_ThreadInfoCache == null || m_ThreadInfoCache.Capacity < threadCount)
                {
                    m_ThreadInfoCache = new List <ThreadInfo>(threadCount);
                }
                m_ThreadInfoCache.Clear();

                // Fetch all thread names
                for (var i = 0; i < threadCount; ++i)
                {
                    frameIterator.SetRoot(m_FrameIndex, i);
                    var groupName  = frameIterator.GetGroupName();
                    var threadName = frameIterator.GetThreadName();
                    var name       = string.IsNullOrEmpty(groupName) ? threadName : groupName + "." + threadName;
                    m_ThreadInfoCache.Add(new ThreadInfo()
                    {
                        groupOrder = GetGroupOrder(name), fullName = name, threadIndex = i
                    });
                }

                m_ThreadInfoCache.Sort();

                for (var i = 0; i < threadCount; ++i)
                {
                    if (m_FullThreadName == m_ThreadInfoCache[i].fullName)
                    {
                        // first check if we have a specific index (some names might be douplicates
                        if (threadIndex == m_ThreadInfoCache[i].threadIndex)
                        {
                            threadIndexInThreadNames = i;
                            break;
                        }
                        // otherwise, store the first fit.
                        else if (threadIndexInThreadNames == FrameDataView.invalidThreadIndex)
                        {
                            threadIndexInThreadNames = i;
                        }
                    }
                }
            }
            // security fallback to avoid index out of bounds
            if (threadIndexInThreadNames == FrameDataView.invalidThreadIndex)
            {
                threadIndexInThreadNames = 0;
            }
        }
Example #21
0
        public static void PullDataStatic(ref FileAccessCaptureData captureData, Dictionary <string, FileAccessMarkerInfo> markers, ref Dictionary <string, int> markerToIDMap, int firstFrameIndex, int lastFrameIndex)
        {
            string error = null;

            captureData.m_FileAccessData.Clear();
            captureData.m_StartTimeNs = ulong.MaxValue;
            captureData.m_EndTimeNs   = ulong.MinValue;

            ProfilerFrameDataIterator frameIter = new ProfilerFrameDataIterator();
            double nsFrameStart;

            for (int frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; ++frameIndex)
            {
                frameIter.SetRoot(frameIndex, 0);

                int threadCount = frameIter.GetThreadCount(frameIndex);
                // iterate over the threads
                for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
                {
                    using (RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView(frameIndex, threadIndex))
                    {
                        if (!frameData.valid)
                        {
                            break;
                        }

                        nsFrameStart = frameData.frameStartTimeNs;
                        if (frameIndex == firstFrameIndex)
                        {
                            if (captureData.m_StartTimeNs > nsFrameStart)
                            {
                                captureData.m_StartTimeNs = nsFrameStart;
                            }
                        }

                        GetMarkerIDs(frameData, markers, ref markerToIDMap);

                        string fullThreadName = GetFullThreadName(frameData.threadGroupName, frameData.threadName);

                        // iterate over the samples to collect up any markers
                        int sampleCount = frameData.sampleCount;
                        for (int i = 0; i < sampleCount; ++i)
                        {
                            s_CheckSamples.Begin();
                            int markerId = frameData.GetSampleMarkerId(i);
                            if (markerId == FrameDataView.invalidMarkerId || !markerToIDMap.ContainsValue(markerId))
                            {
                                s_CheckSamples.End();
                                continue;
                            }

                            string markerName = frameData.GetMarkerName(markerId);
                            Assert.IsTrue(markers.ContainsKey(markerName), string.Format("Marker {0} is not present in requested markers.", markerName));

                            s_CheckSamples.End();

                            s_AddNewMarker.Begin();

                            ulong markerStartTimeNs = Math.Max(frameData.GetSampleStartTimeNs(i) - (ulong)captureData.m_StartTimeNs, 0);
                            ulong sampleLengthNs    = frameData.GetSampleTimeNs(i);

                            // if the marker isn't a continuation of a previous marker, add a new access
                            if (!CheckForContinuationMarker(frameData, ref captureData, threadIndex, markerId, frameIndex, i, markerStartTimeNs, sampleLengthNs))
                            {
                                FileAccessMarker fileAccessMarker = new FileAccessMarker(frameIndex, threadIndex, i);

                                // fill in contexts from Metadata
                                FileAccessMarkerInfo markerInfo = markers[markerName];
                                if (markerInfo.metadataCount == frameData.GetSampleMetadataCount(i))
                                {
                                    markerInfo.metaDataFiller(ref fileAccessMarker, frameData, i);
                                }
                                else if (error == null) // Check the error is only shown once
                                {
                                    error = $"Some markers, such as '{markerName}', have unexpected metadata. This may be because of opening a profile captured with an older version of Unity. Certain values may be missing.";
                                    Debug.LogWarning(error);
                                }

                                if (string.IsNullOrEmpty(fileAccessMarker.filename))
                                {
                                    fileAccessMarker.readablePath     = "Unknown path";
                                    fileAccessMarker.readableFileName = "?";
                                }
                                else
                                {
                                    fileAccessMarker.readablePath     = fileAccessMarker.filename;
                                    fileAccessMarker.readableFileName = Path.GetFileName(fileAccessMarker.readablePath);
                                    if (fileAccessMarker.readablePath.Contains("/Analytics/"))
                                    {
                                        fileAccessMarker.readableFileName += " (Analytics)";
                                    }
                                }

                                fileAccessMarker.startNs  = markerStartTimeNs;
                                fileAccessMarker.lengthNs = sampleLengthNs;
                                fileAccessMarker.endNs    = markerStartTimeNs + sampleLengthNs;

                                fileAccessMarker.startTimeMs = markerStartTimeNs * 0.000001;
                                fileAccessMarker.ms          = fileAccessMarker.lengthNs * 0.000001;

                                fileAccessMarker.markerId   = markerId;
                                fileAccessMarker.type       = markerInfo.fileAccessType;
                                fileAccessMarker.markerName = markerName;
                                fileAccessMarker.threadName = fullThreadName;
                                fileAccessMarker.threadId   = frameData.threadId;

                                captureData.m_FileAccessData.Add(fileAccessMarker);
                            }
                            s_AddNewMarker.End();
                        }
                    }
                }
            }

            foreach (var fileAccessMarker in captureData.m_FileAccessData)
            {
                fileAccessMarker.averageBandwidthMBps = (fileAccessMarker.ms > 0) ? ((float)fileAccessMarker.sizeBytes / (float)fileAccessMarker.ms) * 0.001f : 0.0f;
            }

            frameIter.Dispose();
        }
Example #22
0
        /// Gets the data from the profiler and stores it in our own tree structure.
        /// Uses the undocumented Unity Profiling classes.
        private IEnumerator <float> LoadDataFromProfiler()
        {
            m_AllFunctions = new List <SampledFunction>();

            int id = 0;

            m_root           = new SampledFunction();
            m_root.depth     = 0;
            m_root.id        = id++;
            m_root.frameData = new Dictionary <int, FrameData>();
            m_root.name      = "Frame";
            m_AllFunctions.Add(m_root);
            int first = ProfilerDriver.firstFrameIndex;
            int last  = ProfilerDriver.lastFrameIndex;

            for (int frame = first; frame <= last; ++frame)
            {
                yield return(Mathf.InverseLerp(first, last, frame));

                // The iterator is used to get profile data. It can be set to start on a particular thread
                // at a particular frame. When you call Next(bool enterchildren) it will move on to the
                // next sample. It contains the depth of the callstack for each function, which can
                // be used to work out the tree structure.
                var iterator = new ProfilerFrameDataIterator();
                iterator.SetRoot(frame, 0);
                m_root.frameData.Add(frame,
                                     new FrameData {
                    totalMilliseconds = iterator.durationMS, sampleCount = 1
                });

                // A stack is used to keep a track of the functions further up the call stack.
                Stack <SampledFunction> stack   = new Stack <SampledFunction>();
                SampledFunction         current = m_root;
                stack.Push(m_root);
                while (iterator.Next(true))
                {
                    // If the new item has a greater depth, it must be the child of the current item, so
                    // push it on the stack
                    if (iterator.depth > current.depth)
                    {
                        stack.Push(current);
                    }
                    // If the new item has a lesser depth, we must spool off the stack until we match the
                    // new depth.
                    while (iterator.depth < current.depth)
                    {
                        current = stack.Pop();
                    }

                    if (stack.Peek().children == null)
                    {
                        stack.Peek().children = new Dictionary <string, SampledFunction>();
                    }

                    // We check to see if there is an existing item with the new name in the children of
                    // the item at the top of the stack - if there is, we will just add to it.
                    SampledFunction newFn;
                    if (!stack.Peek().children.TryGetValue(iterator.name, out newFn))
                    {
                        // Otherwise, we must create a new one and add it to the children of the itam at the
                        // top of the stack.
                        newFn       = new SampledFunction();
                        newFn.id    = id++;
                        newFn.name  = iterator.name;
                        newFn.depth = iterator.depth;

                        stack.Peek().children.Add(newFn.name, newFn);
                        // We also add it to the list of all items here.
                        m_AllFunctions.Add(newFn);
                    }
                    current = newFn;

                    // Get an existing framedata for this frame, or create a new one.
                    FrameData frameData;
                    if (!current.frameData.TryGetValue(frame, out frameData))
                    {
                        frameData = new FrameData();
                        current.frameData.Add(frame, frameData);
                    }

                    // Update the frame data.
                    frameData.totalMilliseconds += iterator.durationMS;
                    frameData.sampleCount++;
                }
            }
        }
 public static ProfileMarker Create(ProfilerFrameDataIterator frameData)
 {
     return(Create(frameData.durationMS, frameData.depth));
 }
Example #24
0
        bool GetMarkerInfo(string markerName, int frameIndex, List <string> threadFilters, out int outThreadIndex, out float time, out float duration, out int instanceId)
        {
            ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();

            outThreadIndex = 0;
            time           = 0.0f;
            duration       = 0.0f;
            instanceId     = 0;
            bool found = false;

            int threadCount = frameData.GetThreadCount(frameIndex);
            Dictionary <string, int> threadNameCount = new Dictionary <string, int>();

            for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
            {
                frameData.SetRoot(frameIndex, threadIndex);

                var threadName = frameData.GetThreadName();
                // Name here could be "Worker Thread 1"

                var groupName = frameData.GetGroupName();
                threadName = ProfileData.GetThreadNameWithGroup(threadName, groupName);

                int nameCount = 0;
                threadNameCount.TryGetValue(threadName, out nameCount);
                threadNameCount[threadName] = nameCount + 1;

                var threadNameWithIndex = ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName);

                // To compare on the filter we need to remove the postfix on the thread name
                // "3:Worker Thread 0" -> "1:Worker Thread"
                // The index of the thread (0) is used +1 as a prefix
                // The preceding number (3) is the count of number of threads with this name
                // Unfortunately multiple threads can have the same name
                threadNameWithIndex = ProfileData.CorrectThreadName(threadNameWithIndex);

                if (threadFilters.Contains(threadNameWithIndex))
                {
                    const bool enterChildren = true;
                    while (frameData.Next(enterChildren))
                    {
                        if (frameData.name == markerName)
                        {
                            time           = frameData.startTimeMS;
                            duration       = frameData.durationMS;
                            instanceId     = frameData.instanceId;
                            outThreadIndex = threadIndex;
                            found          = true;
                            break;
                        }
                    }
                }

                if (found)
                {
                    break;
                }
            }

            frameData.Dispose();
            return(found);
        }