예제 #1
0
        private static void OutputProfilerFrame(ProfilerFrame source,
                                                Dictionary <string, int> exportedFrameNameToExportedFrameId,
                                                Dictionary <string, IList <ProfileEvent> > profileEventsPerThread)
        {
            int frameId = 0;

            foreach (var sourceThreadMethod in source.threadMethods)
            {
                var list = new List <ProfileEvent>(sourceThreadMethod.Item2.Count);

                foreach (ProfilerMethod method in sourceThreadMethod.Item2)
                {
                    if (!exportedFrameNameToExportedFrameId.TryGetValue(method.methodName, out int value))
                    {
                        value = frameId;
                        frameId++;
                        exportedFrameNameToExportedFrameId.Add(method.methodName, value);
                    }

                    list.Add(new ProfileEvent(ProfileEventType.Open, value, method.startTime, method.depth));
                    list.Add(new ProfileEvent(ProfileEventType.Close, value, method.endTime, method.depth));
                }

                profileEventsPerThread[sourceThreadMethod.Item1] = OrderForExport(list).ToList();
            }
        }
예제 #2
0
        private static IList <TraceEvent> GetEvents(ProfilerFrame frame)
        {
            var    events     = new List <TraceEvent>();
            int    processId  = Process.GetCurrentProcess().Id;
            int    threadId   = 0;
            string categories = "PERF";

            foreach (var frameThreadMethod in frame.threadMethods.OrderByDescending(x => x.Item1))
            {
                foreach (ProfilerMethod profilerMethod in frameThreadMethod.Item2)
                {
                    //Chrome tracing shows methods with same startTime as parallel, so we add depth to the startTime
                    long startTime = (long)profilerMethod.startTime + profilerMethod.depth;
                    long endTime   = (long)profilerMethod.endTime < startTime
                                                ? startTime
                                                : (long)profilerMethod.endTime;
                    events.Add(new TraceEvent()
                    {
                        name = profilerMethod.methodName,
                        cat  = categories,
                        pid  = processId,
                        ph   = EventType.B,
                        tid  = frameThreadMethod.Item1,
                        ts   = startTime
                    });
                    events.Add(new TraceEvent()
                    {
                        name = profilerMethod.methodName,
                        cat  = categories,
                        pid  = processId,
                        ph   = EventType.E,
                        tid  = frameThreadMethod.Item1,
                        ts   = endTime
                    });
                }

                threadId++;
            }

            if (frame.markers != null)
            {
                foreach (ProfilerMarker marker in frame.markers)
                {
                    events.Add(new TraceEvent()
                    {
                        name = marker.markName,
                        cat  = "EVENTS",
                        pid  = processId,
                        ph   = EventType.I,
                        tid  = "Events",
                        ts   = (long)(marker.time)
                    });
                }
            }

            return(events);
        }
예제 #3
0
        private static void Export(ProfilerFrame source, TextWriter writer, string name)
        {
            var methodNameToId  = new Dictionary <string, int>();
            var eventsPerThread = new Dictionary <string, IList <ProfileEvent> >();

            OutputProfilerFrame(source, methodNameToId, eventsPerThread);

            var orderedFrameNames = methodNameToId.OrderBy(pair => pair.Value).Select(pair => pair.Key).ToArray();

            WriteToFile(eventsPerThread, orderedFrameNames, writer, name);
        }
예제 #4
0
        private static void CollectFrame()
        {
            ProfilerFrame frame = new ProfilerFrame();

            frame.frameNumber   = currentFrame;
            frame.frameLength   = (stopwatch.ElapsedTicks / (double)Stopwatch.Frequency) * 1000000.0;
            frame.threadMethods = PooledList <(string, PooledList <ProfilerMethod>)> .Create();

            foreach (var dataList in collectedMethods.Values)
            {
                if (dataList.Count == 0)
                {
                    continue;
                }
                if (profilingThreads.TryGetValue(dataList[0].threadId, out string threadName))
                {
                    var tuple = frame.threadMethods.SingleOrDefault(x => x.Item1 == threadName);
                    PooledList <ProfilerMethod> outList = null;
                    if (tuple.Item1 == null)
                    {
                        outList = PooledList <ProfilerMethod> .Create();

                        frame.threadMethods.Add((threadName, outList));
                    }
                    else
                    {
                        outList = tuple.Item2;
                    }

                    outList.AddRange(dataList);
                }
            }

            foreach (var dataList in collectedMarkers.Values)
            {
                if (frame.markers == null)
                {
                    frame.markers = PooledList <ProfilerMarker> .Create();
                }
                frame.markers.AddRange(dataList);
            }

            if (collectedFrames.IsFull)
            {
                collectedFrames.Front().Dispose();
            }
            collectedFrames.PushBack(frame);
        }
예제 #5
0
        public static void WriteToFile(ProfilerFrame source, string filePath)
        {
            var file = new FileInfo(filePath);
            var dir  = file.Directory;

            if (!dir.Exists)
            {
                dir.Create();
            }

            if (file.Exists)
            {
                file.Delete();
            }
            using var fs          = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
            using var writeStream = new StreamWriter(fs, Encoding.UTF8);
            Export(source, writeStream, Path.GetFileNameWithoutExtension(filePath));
        }
예제 #6
0
        public static void WriteToFile(string filename, ProfilingFormat format, FrameSelection frameSelection = FrameSelection.Median)
        {
            if (!ProfilingEnabled)
            {
                throw new InvalidOperationException("Cannot write profile to file when profiling is not enabled.");
            }
            ProfilerFrame frame = default;

            if (collectedFrames.IsEmpty)
            {
                return;
            }

            bool needsDispose = false;

            switch (frameSelection)
            {
            case FrameSelection.Median:
                var ordered = collectedFrames.OrderBy(x => x.frameLength).ToArray();
                frame = ordered[(int)Math.Floor(ordered.Length / 2.0)];
                break;

            case FrameSelection.Longest:
                frame = collectedFrames.MaxBy(x => x.frameLength);
                break;

            case FrameSelection.Shortest:
                frame = collectedFrames.MinBy(x => x.frameLength);
                break;

            case FrameSelection.Latest:
                frame = collectedFrames.Back();
                break;

            case FrameSelection.Percentile95:
                ordered = collectedFrames.OrderBy(x => x.frameLength).ToArray();
                int index = ordered.Length - (int)(ordered.Length * 0.05f);
                if (index >= ordered.Length)
                {
                    index = ordered.Length - 1;
                }
                frame = ordered[index];
                break;

            case FrameSelection.All:
                frame             = new ProfilerFrame();
                frame.frameNumber = collectedFrames.Min(x => x.frameNumber);
                frame.frameLength = collectedFrames.Sum(x => x.frameLength);
                frame.markers     = PooledList <ProfilerMarker> .Create();

                double elapsedTime = 0;
                foreach (var collectedFrame in collectedFrames)
                {
                    if (collectedFrame.markers != null)
                    {
                        frame.markers.AddRange(collectedFrame.markers.Select(x =>
                                                                             new ProfilerMarker(x.markName, x.time + elapsedTime)));
                    }
                    elapsedTime += collectedFrame.frameLength;
                }
                frame.threadMethods = PooledList <(string, PooledList <ProfilerMethod>)> .Create();

                elapsedTime = 0;
                foreach (var collectedFrame in collectedFrames)
                {
                    foreach (var collectedFrameThreadMethod in collectedFrame.threadMethods)
                    {
                        var tuple = frame.threadMethods.SingleOrDefault(x => x.Item1 == collectedFrameThreadMethod.Item1);
                        PooledList <ProfilerMethod> outList = null;
                        if (tuple.Item1 == null)
                        {
                            outList = PooledList <ProfilerMethod> .Create();

                            frame.threadMethods.Add((collectedFrameThreadMethod.Item1, outList));
                        }
                        else
                        {
                            outList = tuple.Item2;
                        }
                        outList.AddRange(collectedFrameThreadMethod.Item2.Select(x => new ProfilerMethod(
                                                                                     x.methodName, x.depth, x.startTime + elapsedTime, x.endTime + elapsedTime, x.threadId)));
                    }
                    elapsedTime += collectedFrame.frameLength;
                }

                needsDispose = true;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(frameSelection), frameSelection, null);
            }

            switch (format)
            {
            case ProfilingFormat.SpeedScope:
                SpeedScopeWriter.WriteToFile(frame, filename);
                break;

            case ProfilingFormat.ChromeTracing:
                ChromeTracingWriter.WriteToFile(frame, filename);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(format), format, null);
            }

            if (needsDispose)
            {
                frame.Dispose();
            }
        }
예제 #7
0
        private static void Export(ProfilerFrame source, TextWriter writer, string name)
        {
            var events = GetEvents(source);

            WriteToFile(events, writer, name);
        }