コード例 #1
0
        private static void ConvertToSpeedscope(string fileToConvert, string outputFilename)
        {
            var etlxFilePath = TraceLog.CreateFromEventPipeDataFile(fileToConvert);

            using (var symbolReader = new SymbolReader(System.IO.TextWriter.Null)
            {
                SymbolPath = SymbolPath.MicrosoftSymbolServerPath
            })
                using (var eventLog = new TraceLog(etlxFilePath))
                {
                    var stackSource = new MutableTraceEventStackSource(eventLog)
                    {
                        OnlyManagedCodeStacks = true // EventPipe currently only has managed code stacks.
                    };

                    var computer = new SampleProfilerThreadTimeComputer(eventLog, symbolReader);
                    computer.GenerateThreadTimeStacks(stackSource);

                    SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename);
                }

            if (File.Exists(etlxFilePath))
            {
                File.Delete(etlxFilePath);
            }
        }
コード例 #2
0
        public void WalkTheStackAndExpandSamplesHandlesBrokenStacks(StackSourceFrameIndex kind)
        {
            // Main() calls WRONG
            const double relativeTime = 0.1;
            var          main         = new FakeStackSourceSample(
                relativeTime: relativeTime,
                name: "Main",
                frameIndex: (StackSourceFrameIndex)5,     // 5 is first non-taken enum value
                stackIndex: (StackSourceCallStackIndex)1, // 1 is first non-taken enum value
                callerIndex: StackSourceCallStackIndex.Invalid);
            var wrong = new FakeStackSourceSample(
                relativeTime: relativeTime,
                name: "WRONG",
                frameIndex: kind,
                stackIndex: (StackSourceCallStackIndex)2,
                callerIndex: main.StackIndex);

            var allSamples    = new[] { main, wrong };
            var leafs         = new[] { new SpeedScopeStackSourceWriter.Sample(wrong.StackIndex, -1, wrong.RelativeTime, wrong.Metric, -1) };
            var stackSource   = new StackSourceStub(allSamples);
            var frameNameToId = new Dictionary <string, int>();

            var frameIdToSamples = SpeedScopeStackSourceWriter.WalkTheStackAndExpandSamples(stackSource, leafs, frameNameToId);

            Assert.Equal(0, frameNameToId[main.Name]);
            Assert.False(frameNameToId.ContainsKey(wrong.Name));

            var theOnlySample = frameIdToSamples.Single().Value.Single();

            Assert.Equal(relativeTime, theOnlySample.RelativeTime);
            Assert.Equal(0, theOnlySample.Depth);
        }
コード例 #3
0
        private static void ConvertToSpeedscope(string fileToConvert)
        {
            var symbolReader = new SymbolReader(System.IO.TextWriter.Null)
            {
                SymbolPath = SymbolPath.MicrosoftSymbolServerPath
            };
            var etlxFilePath = TraceLog.CreateFromEventPipeDataFile(fileToConvert);

            var eventLog = new TraceLog(etlxFilePath);

            try
            {
                var stackSource = new MutableTraceEventStackSource(eventLog)
                {
                    OnlyManagedCodeStacks = true // EventPipe currently only has managed code stacks.
                };

                var computer = new SampleProfilerThreadTimeComputer(eventLog, symbolReader);
                computer.GenerateThreadTimeStacks(stackSource);

                var speedScopeFilePath = Path.ChangeExtension(fileToConvert, "speedscope.json");

                SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, speedScopeFilePath);
            }
            finally
            {
                eventLog.Dispose();

                if (File.Exists(etlxFilePath))
                {
                    File.Delete(etlxFilePath);
                }
            }
        }
コード例 #4
0
        public void CloseMetricCanBeZeroIfItDoesNotCreateAProfileEventThatStartsAndEndsAtTheSameMoment()
        {
            const double metric = 0.1;

            var samples = new[]
            {
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, metric: metric, relativeTime: 0.1, depth: 0, callerFrameId: 0),
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, metric: metric, relativeTime: 0.2, depth: 0, callerFrameId: 0),
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, metric: 0.0, relativeTime: 0.3, depth: 0, callerFrameId: 0), // 0.0 metric
            };

            var input = new Dictionary <int, List <SpeedScopeStackSourceWriter.Sample> >()
            {
                { 0, samples.ToList() }
            };

            var aggregatedEvents = SpeedScopeStackSourceWriter.GetAggregatedOrderedProfileEvents(input);

            // we should have:
            //  Open at 0.1 depth 0 and Close 0.3
            Assert.Equal(2, aggregatedEvents.Count);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, aggregatedEvents[0].Type);
            Assert.Equal(0.1, aggregatedEvents[0].RelativeTime);
            Assert.Equal(0, aggregatedEvents[0].Depth);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, aggregatedEvents[1].Type);
            Assert.Equal(0.3, aggregatedEvents[1].RelativeTime);
            Assert.Equal(0, aggregatedEvents[0].Depth);
        }
コード例 #5
0
        // Method copied from https://github.com/dotnet/diagnostics/blob/2c23d3265dd8f642a8d6cf4bb8a135a5ff8b00c2/src/Tools/dotnet-trace/TraceFileFormatConverter.cs#L64
        private static void ConvertToSpeedscope(string fileToConvert, string outputFilename, bool continueOnError = false)
        {
            var etlxFilePath = TraceLog.CreateFromEventPipeDataFile(fileToConvert, null, new TraceLogOptions()
            {
                ContinueOnError = continueOnError
            });

            using (var symbolReader = new SymbolReader(System.IO.TextWriter.Null)
            {
                SymbolPath = SymbolPath.MicrosoftSymbolServerPath
            })
                using (var eventLog = new TraceLog(etlxFilePath))
                {
                    var stackSource = new MutableTraceEventStackSource(eventLog)
                    {
                        OnlyManagedCodeStacks = true // EventPipe currently only has managed code stacks.
                    };

                    var computer = new SampleProfilerThreadTimeComputer(eventLog, symbolReader)
                    {
                        IncludeEventSourceEvents = false // SpeedScope handles only CPU samples, events are not supported
                    };
                    computer.GenerateThreadTimeStacks(stackSource);

                    SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename);
                }

            if (File.Exists(etlxFilePath))
            {
                File.Delete(etlxFilePath);
            }
        }
コード例 #6
0
        public void OrderForExportOrdersTheProfileEventsAsExpectedByTheSpeedScope()
        {
            var profileEvents = new List <SpeedScopeStackSourceWriter.ProfileEvent>()
            {
                new SpeedScopeStackSourceWriter.ProfileEvent(SpeedScopeStackSourceWriter.ProfileEventType.Open, frameId: 0, depth: 0, relativeTime: 0.1),
                new SpeedScopeStackSourceWriter.ProfileEvent(SpeedScopeStackSourceWriter.ProfileEventType.Open, frameId: 1, depth: 1, relativeTime: 0.1),
                new SpeedScopeStackSourceWriter.ProfileEvent(SpeedScopeStackSourceWriter.ProfileEventType.Close, frameId: 1, depth: 1, relativeTime: 0.3),
                new SpeedScopeStackSourceWriter.ProfileEvent(SpeedScopeStackSourceWriter.ProfileEventType.Close, frameId: 0, depth: 0, relativeTime: 0.3),
                new SpeedScopeStackSourceWriter.ProfileEvent(SpeedScopeStackSourceWriter.ProfileEventType.Open, frameId: 2, depth: 0, relativeTime: 0.3),
                new SpeedScopeStackSourceWriter.ProfileEvent(SpeedScopeStackSourceWriter.ProfileEventType.Close, frameId: 2, depth: 0, relativeTime: 0.4),
            };

            profileEvents.Reverse(); // reverse to make sure that it does sort the elements in right way

            var ordered = SpeedScopeStackSourceWriter.OrderForExport(profileEvents).ToArray();

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, ordered[0].Type);
            Assert.Equal(0.1, ordered[0].RelativeTime);
            Assert.Equal(0, ordered[0].Depth);
            Assert.Equal(0, ordered[0].FrameId);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, ordered[1].Type);
            Assert.Equal(0.1, ordered[1].RelativeTime);
            Assert.Equal(1, ordered[1].Depth);
            Assert.Equal(1, ordered[1].FrameId);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, ordered[2].Type);
            Assert.Equal(0.3, ordered[2].RelativeTime);
            Assert.Equal(1, ordered[2].Depth);
            Assert.Equal(1, ordered[2].FrameId);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, ordered[3].Type);
            Assert.Equal(0.3, ordered[3].RelativeTime);
            Assert.Equal(0, ordered[3].Depth);
            Assert.Equal(0, ordered[3].FrameId);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, ordered[4].Type);
            Assert.Equal(0.3, ordered[4].RelativeTime);
            Assert.Equal(0, ordered[4].Depth);
            Assert.Equal(2, ordered[4].FrameId);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, ordered[5].Type);
            Assert.Equal(0.4, ordered[5].RelativeTime);
            Assert.Equal(0, ordered[5].Depth);
            Assert.Equal(2, ordered[5].FrameId);
        }
コード例 #7
0
        private static void Convert(TraceFileFormat format, string fileToConvert, string outputFilename, bool continueOnError = false)
        {
            var etlxFilePath = TraceLog.CreateFromEventPipeDataFile(fileToConvert, null, new TraceLogOptions()
            {
                ContinueOnError = continueOnError
            });

            using (var symbolReader = new SymbolReader(TextWriter.Null)
            {
                SymbolPath = SymbolPath.MicrosoftSymbolServerPath
            })
                using (var eventLog = new TraceLog(etlxFilePath))
                {
                    var stackSource = new MutableTraceEventStackSource(eventLog)
                    {
                        OnlyManagedCodeStacks = true // EventPipe currently only has managed code stacks.
                    };

                    var computer = new SampleProfilerThreadTimeComputer(eventLog, symbolReader)
                    {
                        IncludeEventSourceEvents = false // SpeedScope handles only CPU samples, events are not supported
                    };
                    computer.GenerateThreadTimeStacks(stackSource);

                    switch (format)
                    {
                    case TraceFileFormat.Speedscope:
                        SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename);
                        break;

                    case TraceFileFormat.Chromium:
                        ChromiumStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename, compress: false);
                        break;

                    default:
                        // we should never get here
                        throw new ArgumentException($"Invalid TraceFileFormat \"{format}\"");
                    }
                }

            if (File.Exists(etlxFilePath))
            {
                File.Delete(etlxFilePath);
            }
        }
コード例 #8
0
        public void TwoSamplesCanNotHappenAtTheSameTime()
        {
            const double zeroMetric   = 0.0;
            const double relativeTime = 0.1;

            var samples = new[]
            {
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, metric: zeroMetric, relativeTime: relativeTime, depth: 0, callerFrameId: 0), // 0.0 metric
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, metric: zeroMetric, relativeTime: relativeTime, depth: 0, callerFrameId: 0), // 0.0 metric and same relative time
            };

            var input = new Dictionary <int, List <SpeedScopeStackSourceWriter.Sample> >()
            {
                { 0, samples.ToList() }
            };

            Assert.Throws <ArgumentException>(() => SpeedScopeStackSourceWriter.GetAggregatedOrderedProfileEvents(input));
        }
コード例 #9
0
        public void GetAggregatedOrderedProfileEventsConvertsContinuousSamplesWithPausesToMultipleEvents()
        {
            const double metric = 0.1;

            var samples = new[]
            {
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, callerFrameId: 0, metric: metric, depth: 0, relativeTime: 0.1),
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, callerFrameId: 0, metric: metric, depth: 0, relativeTime: 0.2),

                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, callerFrameId: 0, metric: metric, depth: 0, relativeTime: 0.7),

                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, callerFrameId: 0, metric: metric, depth: 0, relativeTime: 1.1),
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, callerFrameId: 0, metric: metric, depth: 0, relativeTime: 1.2),
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, callerFrameId: 0, metric: metric, depth: 0, relativeTime: 1.3),
            };

            var input = new Dictionary <int, List <SpeedScopeStackSourceWriter.Sample> >()
            {
                { 0, samples.ToList() }
            };

            var aggregatedEvents = SpeedScopeStackSourceWriter.GetAggregatedOrderedProfileEvents(input);

            // we should have <0.1, 0.3> and <0.7, 0.8> (the tool would ignore <0.7, 0.7>) and <1.1, 1.4>
            Assert.Equal(6, aggregatedEvents.Count);

            Assert.Equal(0.1, aggregatedEvents[0].RelativeTime);
            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, aggregatedEvents[0].Type);
            Assert.Equal(0.2 + metric, aggregatedEvents[1].RelativeTime);
            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, aggregatedEvents[1].Type);

            Assert.Equal(0.7, aggregatedEvents[2].RelativeTime);
            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, aggregatedEvents[2].Type);
            Assert.Equal(0.7 + metric, aggregatedEvents[3].RelativeTime);
            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, aggregatedEvents[3].Type);

            Assert.Equal(1.1, aggregatedEvents[4].RelativeTime);
            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, aggregatedEvents[4].Type);
            Assert.Equal(1.3 + metric, aggregatedEvents[5].RelativeTime);
            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, aggregatedEvents[5].Type);
        }
コード例 #10
0
        public void WalkTheStackAndExpandSamplesProducesFullInformation()
        {
            // Main() calls A() calls B()
            const double relativeTime = 0.1;
            var          main         = new FakeStackSourceSample(
                relativeTime: relativeTime,
                name: "Main",
                frameIndex: (StackSourceFrameIndex)5,     // 5 is first non-taken enum value
                stackIndex: (StackSourceCallStackIndex)1, // 1 is first non-taken enum value
                callerIndex: StackSourceCallStackIndex.Invalid);
            var a = new FakeStackSourceSample(
                relativeTime: relativeTime,
                name: "A",
                frameIndex: (StackSourceFrameIndex)6,
                stackIndex: (StackSourceCallStackIndex)2,
                callerIndex: main.StackIndex);
            var b = new FakeStackSourceSample(
                relativeTime: relativeTime,
                name: "B",
                frameIndex: (StackSourceFrameIndex)7,
                stackIndex: (StackSourceCallStackIndex)3,
                callerIndex: a.StackIndex);

            var allSamples    = new[] { main, a, b };
            var leafs         = new[] { new SpeedScopeStackSourceWriter.Sample(b.StackIndex, -1, b.RelativeTime, b.Metric, -1) };
            var stackSource   = new StackSourceStub(allSamples);
            var frameNameToId = new Dictionary <string, int>();

            var frameIdToSamples = SpeedScopeStackSourceWriter.WalkTheStackAndExpandSamples(stackSource, leafs, frameNameToId);

            Assert.Equal(0, frameNameToId[main.Name]);
            Assert.Equal(1, frameNameToId[a.Name]);
            Assert.Equal(2, frameNameToId[b.Name]);

            Assert.All(frameIdToSamples.Select(pair => pair.Value), samples => Assert.Equal(relativeTime, samples.Single().RelativeTime));
            Assert.Equal(0, frameIdToSamples[0].Single().Depth);
            Assert.Equal(1, frameIdToSamples[1].Single().Depth);
            Assert.Equal(2, frameIdToSamples[2].Single().Depth);
        }
コード例 #11
0
        public void GetSortedSamplesReturnsSamplesSortedByRelativeTimeAndGrouppedByThread()
        {
            const string ThreadName = "Thread (123)";
            var          thread_1   = new FakeStackSourceSample(
                relativeTime: 0.1,
                name: ThreadName,
                frameIndex: (StackSourceFrameIndex)5,     // 5 is first non-taken enum value
                stackIndex: (StackSourceCallStackIndex)1, // 1 is first non-taken enum value
                callerIndex: StackSourceCallStackIndex.Invalid);
            var a_1 = new FakeStackSourceSample(
                relativeTime: 0.1,
                name: "A",
                frameIndex: (StackSourceFrameIndex)6,
                stackIndex: (StackSourceCallStackIndex)2,
                callerIndex: thread_1.StackIndex);
            var thread_2 = new FakeStackSourceSample(
                relativeTime: 0.2,
                name: ThreadName,
                frameIndex: (StackSourceFrameIndex)5,     // 5 is first non-taken enum value
                stackIndex: (StackSourceCallStackIndex)3, // 1 is first non-taken enum value
                callerIndex: StackSourceCallStackIndex.Invalid);
            var a_2 = new FakeStackSourceSample(
                relativeTime: 0.2,
                name: "A",
                frameIndex: (StackSourceFrameIndex)6,
                stackIndex: (StackSourceCallStackIndex)4,
                callerIndex: thread_2.StackIndex);

            var sourceSamples = new[] { thread_1, thread_2, a_2, a_1 };

            var stackSource = new StackSourceStub(sourceSamples);

            var result = SpeedScopeStackSourceWriter.GetSortedSamplesPerThread(stackSource)[ThreadName];

            Assert.Equal(0.1, result[0].RelativeTime);
            Assert.Equal(0.1, result[1].RelativeTime);
            Assert.Equal(0.2, result[2].RelativeTime);
            Assert.Equal(0.2, result[2].RelativeTime);
        }
コード例 #12
0
        public void GetAggregatedOrderedProfileEventsConvertsContinuousSamplesWithDifferentCallerIdToMultipleEvents()
        {
            const double metric = 0.1;

            var samples = new[]
            {
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, metric: metric, relativeTime: 0.1, depth: 0, callerFrameId: 0),
                new SpeedScopeStackSourceWriter.Sample((StackSourceCallStackIndex)1, metric: metric, relativeTime: 0.2, depth: 0, callerFrameId: 1), // callerFrameId change!
            };

            var input = new Dictionary <int, List <SpeedScopeStackSourceWriter.Sample> >()
            {
                { 0, samples.ToList() }
            };

            var aggregatedEvents = SpeedScopeStackSourceWriter.GetAggregatedOrderedProfileEvents(input);

            // we should have:
            //  Open at 0.1 depth 0 and Close 0.2
            //  Open at 0.2 depth 0 and Close 0.3
            Assert.Equal(4, aggregatedEvents.Count);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, aggregatedEvents[0].Type);
            Assert.Equal(0.1, aggregatedEvents[0].RelativeTime);
            Assert.Equal(0, aggregatedEvents[0].Depth);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, aggregatedEvents[1].Type);
            Assert.Equal(0.1 + metric, aggregatedEvents[1].RelativeTime);
            Assert.Equal(0, aggregatedEvents[0].Depth);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Open, aggregatedEvents[2].Type);
            Assert.Equal(0.2, aggregatedEvents[2].RelativeTime);
            Assert.Equal(0, aggregatedEvents[2].Depth);

            Assert.Equal(SpeedScopeStackSourceWriter.ProfileEventType.Close, aggregatedEvents[3].Type);
            Assert.Equal(0.2 + metric, aggregatedEvents[3].RelativeTime);
            Assert.Equal(0, aggregatedEvents[3].Depth);
        }