-
Notifications
You must be signed in to change notification settings - Fork 32
Perfetto plugin - Add table for CPU scheduling events #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
KyleStorck
merged 4 commits into
microsoft:perfetto
from
KyleStorck:user/kylsto/cpu_scheduling
Jul 29, 2021
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
PerfettoCds/Pipeline/CompositeDataCookers/PerfettoCpuSchedEventCooker.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Microsoft.Performance.SDK; | ||
| using Microsoft.Performance.SDK.Extensibility; | ||
| using Microsoft.Performance.SDK.Extensibility.DataCooking; | ||
| using Microsoft.Performance.SDK.Processing; | ||
| using PerfettoCds.Pipeline.DataOutput; | ||
| using PerfettoProcessor; | ||
|
|
||
| namespace PerfettoCds.Pipeline.DataCookers | ||
| { | ||
| /// <summary> | ||
| /// Pulls data from multiple individual SQL tables and joins them to create a CPU scheduling event | ||
| /// </summary> | ||
| public sealed class PerfettoCpuSchedEventCooker : CookedDataReflector, ICompositeDataCookerDescriptor | ||
| { | ||
| public static readonly DataCookerPath DataCookerPath = PerfettoPluginConstants.CpuSchedEventCookerPath; | ||
|
|
||
| public string Description => "CPU scheduling event composite cooker"; | ||
|
|
||
| public DataCookerPath Path => DataCookerPath; | ||
|
|
||
| // Declare all of the cookers that are used by this CompositeCooker. | ||
| public IReadOnlyCollection<DataCookerPath> RequiredDataCookers => new[] | ||
| { | ||
| PerfettoPluginConstants.ThreadCookerPath, | ||
| PerfettoPluginConstants.ProcessCookerPath, | ||
| PerfettoPluginConstants.SchedSliceCookerPath | ||
| }; | ||
|
|
||
| [DataOutput] | ||
| public ProcessedEventData<PerfettoCpuSchedEvent> CpuSchedEvents { get; } | ||
|
|
||
| public PerfettoCpuSchedEventCooker() : base(PerfettoPluginConstants.CpuSchedEventCookerPath) | ||
| { | ||
| this.CpuSchedEvents = | ||
| new ProcessedEventData<PerfettoCpuSchedEvent>(); | ||
| } | ||
|
|
||
| public void OnDataAvailable(IDataExtensionRetrieval requiredData) | ||
| { | ||
| // Gather the data from all the SQL tables | ||
| var threadData = requiredData.QueryOutput<ProcessedEventData<PerfettoThreadEvent>>(new DataOutputPath(PerfettoPluginConstants.ThreadCookerPath, nameof(PerfettoThreadCooker.ThreadEvents))); | ||
| var processData = requiredData.QueryOutput<ProcessedEventData<PerfettoProcessEvent>>(new DataOutputPath(PerfettoPluginConstants.ProcessCookerPath, nameof(PerfettoProcessCooker.ProcessEvents))); | ||
| var schedSliceData = requiredData.QueryOutput<ProcessedEventData<PerfettoSchedSliceEvent>>(new DataOutputPath(PerfettoPluginConstants.SchedSliceCookerPath, nameof(PerfettoSchedSliceCooker.SchedSliceEvents))); | ||
|
|
||
| // The sched slice data contains the timings, CPU, priority, and end state info. We get the process and thread from | ||
| // those respective tables | ||
| var joined = from schedSlice in schedSliceData | ||
| join thread in threadData on schedSlice.Utid equals thread.Utid | ||
| join process in processData on thread.Upid equals process.Upid | ||
| select new { schedSlice, thread, process }; | ||
|
|
||
| // Create events out of the joined results | ||
| foreach (var result in joined) | ||
| { | ||
| PerfettoCpuSchedEvent ev = new PerfettoCpuSchedEvent | ||
| ( | ||
| result.process.Name, | ||
| result.thread.Name, | ||
| new TimestampDelta(result.schedSlice.Duration), | ||
| new Timestamp(result.schedSlice.Timestamp), | ||
| new Timestamp(result.schedSlice.Timestamp + result.schedSlice.Duration), | ||
| result.schedSlice.Cpu, | ||
| result.schedSlice.EndStateStr, | ||
| result.schedSlice.Priority | ||
| ); | ||
| this.CpuSchedEvents.AddEvent(ev); | ||
| } | ||
| this.CpuSchedEvents.FinalizeData(); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
| using Microsoft.Performance.SDK; | ||
|
|
||
| namespace PerfettoCds.Pipeline.DataOutput | ||
| { | ||
| /// <summary> | ||
| /// A CPU scheduled event that displays which process and threads were running on which CPUs at specific times. | ||
| /// </summary> | ||
| public readonly struct PerfettoCpuSchedEvent | ||
| { | ||
| public string ProcessName { get; } | ||
| public string ThreadName { get; } | ||
| public TimestampDelta Duration { get; } | ||
| public Timestamp StartTimestamp { get; } | ||
| public Timestamp EndTimestamp { get; } | ||
| public long Cpu { get; } | ||
| public string EndState { get; } | ||
| public long Priority { get; } | ||
|
|
||
| public PerfettoCpuSchedEvent(string processName, | ||
| string threadName, | ||
| TimestampDelta duration, | ||
| Timestamp startTimestamp, | ||
| Timestamp endTimestamp, | ||
| long cpu, | ||
| string endState, | ||
| long priority) | ||
| { | ||
| this.ProcessName = processName; | ||
| this.ThreadName = threadName; | ||
| this.Duration = duration; | ||
| this.StartTimestamp = startTimestamp; | ||
| this.EndTimestamp = endTimestamp; | ||
| this.Cpu = cpu; | ||
| this.EndState = endState; | ||
| this.Priority = priority; | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
PerfettoCds/Pipeline/SourceDataCookers/PerfettoSchedSliceCooker.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
| using Microsoft.Performance.SDK; | ||
| using Microsoft.Performance.SDK.Extensibility; | ||
| using Microsoft.Performance.SDK.Extensibility.DataCooking; | ||
| using Microsoft.Performance.SDK.Extensibility.DataCooking.SourceDataCooking; | ||
| using Microsoft.Performance.SDK.Processing; | ||
| using System.Collections.Generic; | ||
| using System.Threading; | ||
| using PerfettoCds.Pipeline.Events; | ||
| using PerfettoProcessor; | ||
|
|
||
| namespace PerfettoCds | ||
| { | ||
| /// <summary> | ||
| /// Cooks the data from the SchedSlice table in Perfetto traces | ||
| /// </summary> | ||
| public sealed class PerfettoSchedSliceCooker : BaseSourceDataCooker<PerfettoSqlEventKeyed, PerfettoSourceParser, string> | ||
| { | ||
| public override string Description => "Processes events from the sched_slice Perfetto SQL table"; | ||
|
|
||
| // | ||
| // The data this cooker outputs. Tables or other cookers can query for this data | ||
| // via the SDK runtime | ||
| // | ||
| [DataOutput] | ||
| public ProcessedEventData<PerfettoSchedSliceEvent> SchedSliceEvents { get; } | ||
|
|
||
| // Instructs runtime to only send events with the given keys this data cooker | ||
| public override ReadOnlyHashSet<string> DataKeys => | ||
| new ReadOnlyHashSet<string>(new HashSet<string> { PerfettoPluginConstants.SchedSliceEvent }); | ||
|
|
||
|
|
||
| public PerfettoSchedSliceCooker() : base(PerfettoPluginConstants.SchedSliceCookerPath) | ||
| { | ||
| this.SchedSliceEvents = new ProcessedEventData<PerfettoSchedSliceEvent>(); | ||
| } | ||
|
|
||
| public override DataProcessingResult CookDataElement(PerfettoSqlEventKeyed perfettoEvent, PerfettoSourceParser context, CancellationToken cancellationToken) | ||
| { | ||
| this.SchedSliceEvents.AddEvent((PerfettoSchedSliceEvent)perfettoEvent.SqlEvent); | ||
|
|
||
| return DataProcessingResult.Processed; | ||
| } | ||
|
|
||
| public override void EndDataCooking(CancellationToken cancellationToken) | ||
| { | ||
| base.EndDataCooking(cancellationToken); | ||
| this.SchedSliceEvents.FinalizeData(); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
| using Microsoft.Performance.SDK.Extensibility; | ||
| using Microsoft.Performance.SDK.Processing; | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Security.Cryptography; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using PerfettoCds.Pipeline.DataOutput; | ||
| using Microsoft.Performance.SDK; | ||
| using PerfettoCds.Pipeline.DataCookers; | ||
| using System.Linq; | ||
|
|
||
| namespace PerfettoCds.Pipeline.Tables | ||
| { | ||
| [Table] | ||
| public class PerfettoCpuSchedTable | ||
| { | ||
| public static TableDescriptor TableDescriptor => new TableDescriptor( | ||
| Guid.Parse("{db17169e-afe5-41f6-ba24-511af1d869f9}"), | ||
| "Perfetto CPU Scheduler Events", | ||
| "Displays CPU scheduling events for processes and threads", | ||
| "Perfetto", | ||
| requiredDataCookers: new List<DataCookerPath> { PerfettoPluginConstants.CpuSchedEventCookerPath } | ||
| ); | ||
|
|
||
| private static readonly ColumnConfiguration ProcessNameColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{91a51bf2-85d6-4932-9df5-dc44445e8521}"), "Process", "Name of the process"), | ||
| new UIHints { Width = 210 }); | ||
|
|
||
| private static readonly ColumnConfiguration ThreadNameColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{62c7c290-3803-4a1a-8bcb-a4f441dc35b6}"), "Thread", "Name of the thread"), | ||
| new UIHints { Width = 210 }); | ||
|
|
||
| private static readonly ColumnConfiguration StartTimestampColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{9c242b6d-bc9a-440d-8eff-82b1b6571d38}"), "StartTimestamp", "Start timestamp for the event"), | ||
| new UIHints { Width = 120 }); | ||
|
|
||
| private static readonly ColumnConfiguration EndTimestampColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{5d37669b-7ae3-471b-97b2-06b593565cd6}"), "EndTimestamp", "End timestamp for the event"), | ||
| new UIHints { Width = 120 }); | ||
|
|
||
| private static readonly ColumnConfiguration DurationColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{1e1d2517-9bf9-4533-b00f-9744021dcf05}"), "Duration", "Duration of the event"), | ||
| new UIHints { Width = 70 }); | ||
|
|
||
| private static readonly ColumnConfiguration CpuColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{704e6901-bc63-46b4-b426-c0642342c991}"), "Cpu", "The CPU this event happened on"), | ||
| new UIHints { Width = 70, SortOrder = SortOrder.Ascending }); | ||
|
|
||
| private static readonly ColumnConfiguration EndStateColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{9f33703d-d2d6-49b1-8d0c-758f4a875d2b}"), "EndState", "Ending state of the event"), | ||
| new UIHints { Width = 70 }); | ||
|
|
||
| private static readonly ColumnConfiguration PriorityColumn = new ColumnConfiguration( | ||
| new ColumnMetadata(new Guid("{73984a25-99b1-43a9-8412-c57b55de5518}"), "Priority", "Priority of the event"), | ||
| new UIHints { Width = 70 }); | ||
|
|
||
| public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) | ||
| { | ||
| // Get data from the cooker | ||
| var events = tableData.QueryOutput<ProcessedEventData<PerfettoCpuSchedEvent>>( | ||
| new DataOutputPath(PerfettoPluginConstants.CpuSchedEventCookerPath, nameof(PerfettoCpuSchedEventCooker.CpuSchedEvents))); | ||
|
|
||
| var test = events.OrderBy(x => x.Cpu); | ||
|
|
||
| // Start construction of the column order. Pivot on process and thread | ||
| List<ColumnConfiguration> allColumns = new List<ColumnConfiguration>() | ||
| { | ||
| CpuColumn, | ||
| ProcessNameColumn, | ||
| ThreadNameColumn, | ||
| TableConfiguration.PivotColumn, // Columns before this get pivotted on | ||
| DurationColumn, | ||
| EndStateColumn, | ||
| PriorityColumn, | ||
| TableConfiguration.GraphColumn, // Columns after this get graphed | ||
| StartTimestampColumn, | ||
| EndTimestampColumn | ||
| }; | ||
|
|
||
| var tableGenerator = tableBuilder.SetRowCount((int)events.Count); | ||
| var baseProjection = Projection.Index(events); | ||
|
|
||
| tableGenerator.AddColumn(CpuColumn, baseProjection.Compose(x => x.Cpu)); | ||
| tableGenerator.AddColumn(ProcessNameColumn, baseProjection.Compose(x => x.ProcessName)); | ||
| tableGenerator.AddColumn(ThreadNameColumn, baseProjection.Compose(x => x.ThreadName)); | ||
| tableGenerator.AddColumn(DurationColumn, baseProjection.Compose(x => x.Duration)); | ||
| tableGenerator.AddColumn(EndStateColumn, baseProjection.Compose(x => x.EndState)); | ||
| tableGenerator.AddColumn(PriorityColumn, baseProjection.Compose(x => x.Priority)); | ||
| tableGenerator.AddColumn(StartTimestampColumn, baseProjection.Compose(x => x.StartTimestamp)); | ||
| tableGenerator.AddColumn(EndTimestampColumn, baseProjection.Compose(x => x.EndTimestamp)); | ||
|
|
||
| var tableConfig = new TableConfiguration("Perfetto CPU Scheduling") | ||
| { | ||
| Columns = allColumns, | ||
| Layout = TableLayoutStyle.GraphAndTable | ||
| }; | ||
| tableConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); | ||
| tableConfig.AddColumnRole(ColumnRole.EndTime, EndTimestampColumn.Metadata.Guid); | ||
| tableConfig.AddColumnRole(ColumnRole.Duration, DurationColumn.Metadata.Guid); | ||
|
|
||
| tableBuilder.AddTableConfiguration(tableConfig).SetDefaultTableConfiguration(tableConfig); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.