Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions LTTngDataExtensions/DataOutputTypes/IExecutionEvent.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using System.Collections.Generic;
using Microsoft.Performance.SDK;

namespace LTTngDataExtensions.SourceDataCookers.Thread
Expand All @@ -23,5 +24,6 @@ public interface IExecutionEvent
Timestamp SwitchInTime { get; }
Timestamp SwitchOutTime { get; }
Timestamp NextThreadPreviousSwitchOutTime { get; }
IReadOnlyDictionary<string, long> PerformanceCountersDiffByName { get; }
}
}
18 changes: 18 additions & 0 deletions LTTngDataExtensions/SourceDataCookers/Thread/ContextSwitch.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using System.Collections.Generic;
using Microsoft.Performance.SDK;
using LTTngCds.CookerData;
using CtfPlayback.Metadata;

namespace LTTngDataExtensions.SourceDataCookers.Thread
{
Expand All @@ -23,6 +25,7 @@ public class ContextSwitch
private TimestampDelta waitTime;
private Timestamp switchInTime;
private Timestamp nextThreadPreviousSwitchOutTime;
private Dictionary<string, long> performanceCountersByName;

public ContextSwitch(LTTngEvent data, ThreadInfo nextThread, ThreadInfo previousThread, uint cpu)
{
Expand Down Expand Up @@ -61,6 +64,20 @@ public ContextSwitch(LTTngEvent data, ThreadInfo nextThread, ThreadInfo previous
this.previousCommand = data.Payload.ReadFieldAsArray("_prev_comm").GetValueAsString();
this.switchInTime = data.Timestamp;
this.nextThreadPreviousSwitchOutTime = nextThread.previousSwitchOutTime;

// PMU counters (e.g. _perf_cpu_instructions) are added to the stream event context by "lttng add-context -t perf:cpu:..."
this.performanceCountersByName = new Dictionary<string, long>();
var eventContext = data.StreamDefinedEventContext;
if (eventContext != null)
{
foreach (var field in eventContext.FieldsByName)
{
if (field.Value.FieldType == CtfTypes.Integer && field.Key.Contains("perf"))
{
this.performanceCountersByName[field.Key] = eventContext.ReadFieldAsInt64(field.Key);
}
}
}
}

public uint Cpu => this.cpu;
Expand All @@ -78,5 +95,6 @@ public ContextSwitch(LTTngEvent data, ThreadInfo nextThread, ThreadInfo previous
public TimestampDelta WaitTime => this.waitTime;
public Timestamp SwitchInTime => this.switchInTime;
public Timestamp NextThreadPreviousSwitchOutTime => this.nextThreadPreviousSwitchOutTime;
public IReadOnlyDictionary<string, long> PerformanceCountersByName => this.performanceCountersByName;
}
}
19 changes: 19 additions & 0 deletions LTTngDataExtensions/SourceDataCookers/Thread/ExecutionEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ public class ExecutionEvent
private Timestamp switchInTime;
private Timestamp switchOutTime;
private Timestamp nextThreadPreviousSwitchOutTime;
private Dictionary<string, long> performanceCountersDiffByName;

public ExecutionEvent(ContextSwitch contextSwitch, Timestamp switchOutTime)
: this(contextSwitch, null, switchOutTime)
{
}

public ExecutionEvent(ContextSwitch contextSwitch, ContextSwitch switchOutContextSwitch, Timestamp switchOutTime)
{
this.cpu = contextSwitch.Cpu;
this.nextPid = contextSwitch.NextPid;
Expand All @@ -46,6 +52,18 @@ public ExecutionEvent(ContextSwitch contextSwitch, Timestamp switchOutTime)
this.switchInTime = contextSwitch.SwitchInTime;
this.switchOutTime = switchOutTime;
this.nextThreadPreviousSwitchOutTime = contextSwitch.NextThreadPreviousSwitchOutTime;

this.performanceCountersDiffByName = new Dictionary<string, long>();
if (switchOutContextSwitch != null)
{
foreach (var counter in contextSwitch.PerformanceCountersByName)
{
if (switchOutContextSwitch.PerformanceCountersByName.TryGetValue(counter.Key, out long switchOutValue))
{
this.performanceCountersDiffByName[counter.Key] = switchOutValue - counter.Value;
Comment thread
jhpohovey marked this conversation as resolved.
}
}
}
}

public void RecoverPids(Dictionary<int, int> recoveredPids)
Expand Down Expand Up @@ -90,5 +108,6 @@ private int reconstructPid(string pid)
public Timestamp SwitchInTime => this.switchInTime;
public Timestamp SwitchOutTime => this.switchOutTime;
public Timestamp NextThreadPreviousSwitchOutTime => this.nextThreadPreviousSwitchOutTime;
public IReadOnlyDictionary<string, long> PerformanceCountersDiffByName => this.performanceCountersDiffByName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -577,19 +577,6 @@ void ProcessThreadMetadata(LTTngEvent data, ThreadInfo thread)
public void ProcessContextSwitch(LTTngEvent data, LTTngContext context)
{
int prevTid = data.Payload.ReadFieldAsInt32("_prev_tid");
if (lastContextSwitch.TryGetValue(context.CurrentCpu, out ContextSwitch previousContextSwitch))
{
if (prevTid == previousContextSwitch.NextTid)
{
processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, data.Timestamp));
}
else
{
///If we missed context switch events,
processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, previousContextSwitch.SwitchInTime));
}

}
int nextTid = data.Payload.ReadFieldAsInt32("_next_tid");
ThreadInfo.ThreadState switchOutState;
var prevStateValue = data.Payload.FieldsByName["_prev_state"];
Expand Down Expand Up @@ -620,17 +607,34 @@ public void ProcessContextSwitch(LTTngEvent data, LTTngContext context)
}

ThreadInfo nextThread;
ContextSwitch currentContextSwitch;
if (runningThreads.TryGetValue(nextTid, out nextThread))
{
lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu);
currentContextSwitch = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu);
nextThread.SwitchIn(data.Timestamp);
}
else
{
nextThread = new ThreadInfo(nextTid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING);
lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu);
currentContextSwitch = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu);
this.AddNewThread(nextThread);
}

// The execution event for the previous context switch is completed here so the PMU counter deltas can be computed against this switch-out.
if (lastContextSwitch.TryGetValue(context.CurrentCpu, out ContextSwitch previousContextSwitch))
{
if (prevTid == previousContextSwitch.NextTid)
{
processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, currentContextSwitch, data.Timestamp));
}
else
{
///If we missed context switch events,
processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, previousContextSwitch.SwitchInTime));
}
}

lastContextSwitch[context.CurrentCpu] = currentContextSwitch;
}

public void ProcessThreadExit(LTTngEvent data)
Expand Down
29 changes: 29 additions & 0 deletions LTTngDataExtensions/Tables/ExecutionEventTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,26 @@ public class ExecutionEventTable
new ColumnMetadata(new Guid("{5AB96EE5-FE5C-45AE-9BA2-965EFF4833D8}"), "Last Switch-Out Time"),
new UIHints { Width = 80, });

private static readonly ColumnConfiguration instructionCountColumn =
new ColumnConfiguration(
new ColumnMetadata(new Guid("{63447522-514D-4F7D-81E0-544E0670BB1D}"), "Instruction Count"),
new UIHints { Width = 80, });

private static readonly ColumnConfiguration lastLevelCacheMissesColumn =
new ColumnConfiguration(
new ColumnMetadata(new Guid("{7EB3DBFA-B1CA-4CB7-9D70-66E0BEFA0F32}"), "LLC Misses"),
new UIHints { Width = 80, });

private static readonly ColumnConfiguration cpuCycleColumn =
new ColumnConfiguration(
new ColumnMetadata(new Guid("{AC255EA6-BA80-4A7D-BCF5-710B6B3618A9}"), "CPU Cycle"),
new UIHints { Width = 80, });

private static readonly ColumnConfiguration cacheMissesColumn =
new ColumnConfiguration(
new ColumnMetadata(new Guid("{6BBB2F84-4215-46CF-9C92-FA79DB8DE55C}"), "Cache Misses"),
new UIHints { Width = 80, });

private static readonly ColumnConfiguration cpuUsageInViewportPreset = new ColumnConfiguration(
new ColumnMetadata(new Guid("{0cf6ffa6-2f41-4460-a201-718c37cbf413}"), "CPU Usage (in view)"),
new UIHints
Expand Down Expand Up @@ -271,6 +291,10 @@ public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieva
table.AddColumn(switchInTimeColumn, switchInTime);
table.AddColumn(switchOutTimeColumn, switchOutTime);
table.AddColumn(previousPidColumn, Projection.CreateUsingFuncAdaptor((i) => threads[i].PreviousPid));
table.AddColumn(instructionCountColumn, Projection.CreateUsingFuncAdaptor((i) => GetPerformanceCounterDiff(threads[i], "_perf_cpu_instructions")));
table.AddColumn(lastLevelCacheMissesColumn, Projection.CreateUsingFuncAdaptor((i) => GetPerformanceCounterDiff(threads[i], "_perf_cpu_LLC_load_misses")));
table.AddColumn(cpuCycleColumn, Projection.CreateUsingFuncAdaptor((i) => GetPerformanceCounterDiff(threads[i], "_perf_cpu_cpu_cycles")));
table.AddColumn(cacheMissesColumn, Projection.CreateUsingFuncAdaptor((i) => GetPerformanceCounterDiff(threads[i], "_perf_cpu_cache_misses")));
Comment thread
jhpohovey marked this conversation as resolved.
table.AddColumn(nextCommandColumn, Projection.CreateUsingFuncAdaptor((i) => threads[i].NextImage));
table.AddColumn(previousCommandColumn, Projection.CreateUsingFuncAdaptor((i) => threads[i].PreviousImage));

Expand All @@ -294,6 +318,11 @@ public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieva
table.AddColumn(cpuUsagePreset, cpuUsageColumn);
table.AddColumn(percentCpuUsagePreset, percentCpuUsageColumn);
}

private static long GetPerformanceCounterDiff(IExecutionEvent executionEvent, string counterName)
{
return executionEvent.PerformanceCountersDiffByName.TryGetValue(counterName, out long value) ? value : 0;
}
}

struct ReduceTimeSinceLastDiff
Expand Down
Loading