public override void Build(ITableBuilder tableBuilder) { if (PerfDataTxtLogParsed == null || PerfDataTxtLogParsed.Count == 0) { return; } var firstPerfDataTxtLogParsed = PerfDataTxtLogParsed.First().Value; // First Log // Init IpStackFrames = new ConcurrentDictionary <long, StackFrame>(); SampleThreadDict = new ConcurrentDictionary <long, int>(); SampleProcessDict = new ConcurrentDictionary <long, string>(); SampleStackWalkEvent = new ConcurrentDictionary <long, ManualResetEvent>(); var baseProjection = Projection.CreateUsingFuncAdaptor(new Func <int, LinuxPerfScriptStackSourceSample>(i => firstPerfDataTxtLogParsed.GetLinuxPerfScriptSampleByIndex((StackSourceSampleIndex)i))); // Calculate sample weights var sampleWeights = CalculateSampleWeights(firstPerfDataTxtLogParsed); var oneNs = new TimestampDelta(1); var weightProj = baseProjection.Compose(s => s.SampleIndex == StackSourceSampleIndex.Invalid ? TimestampDelta.Zero : new TimestampDelta(Convert.ToInt64(sampleWeights[(int)s.SampleIndex] * 1000000))); // Constant columns var sampleIndex = baseProjection.Compose(s => (long)s.SampleIndex); var timeStampProjection = baseProjection.Compose(s => s.SampleIndex == StackSourceSampleIndex.Invalid ? Timestamp.Zero : new Timestamp(Convert.ToInt64(s.TimeRelativeMSec * 1000000))); var cpuProjection = baseProjection.Compose(s => s.SampleIndex == StackSourceSampleIndex.Invalid ? -1 : s.CpuNumber); var countProjection = baseProjection.Compose(s => 1); var ipStackFrameProjection = baseProjection.Compose(s => GetIpStackFrame(s, firstPerfDataTxtLogParsed)?.Frame); var ipModuleProjection = baseProjection.Compose(s => GetIpStackFrame(s, firstPerfDataTxtLogParsed)?.Module); var threadIdProjection = baseProjection.Compose(s => GetThreadId(s, firstPerfDataTxtLogParsed)); var processProjection = baseProjection.Compose(s => GetProcess(s, firstPerfDataTxtLogParsed)); // For calculating cpu % var timeStampStartProjection = baseProjection.Compose(s => s.SampleIndex == StackSourceSampleIndex.Invalid ? Timestamp.Zero : new Timestamp(Convert.ToInt64(s.TimeRelativeMSec * 1000000)) - new TimestampDelta(Convert.ToInt64(sampleWeights[(int)s.SampleIndex] * 1000000))); IProjection <int, Timestamp> viewportClippedStartTimeProj = Projection.ClipTimeToVisibleDomain.Create(timeStampStartProjection); IProjection <int, Timestamp> viewportClippedEndTimeProj = Projection.ClipTimeToVisibleDomain.Create(timeStampProjection); IProjection <int, TimestampDelta> clippedWeightProj = Projection.Select( viewportClippedEndTimeProj, viewportClippedStartTimeProj, new ReduceTimeSinceLastDiff()); IProjection <int, double> weightPercentProj = Projection.VisibleDomainRelativePercent.Create(clippedWeightProj); IProjection <int, int> countProj = SequentialGenerator.Create( firstPerfDataTxtLogParsed.SampleIndexLimit, Projection.Constant(1), Projection.Constant(0)); // // Table Configurations describe how your table should be presented to the user: // the columns to show, what order to show them, which columns to aggregate, and which columns to graph. // You may provide a number of columns in your table, but only want to show a subset of them by default so as not to overwhelm the user. // The user can still open the table properties to turn on or off columns. // The table configuration class also exposes four (4) columns UI explicitly recognizes: Pivot Column, Graph Column, Left Freeze Column, Right Freeze Column // For more information about what these columns do, go to "Advanced Topics" -> "Table Configuration" in our Wiki. Link can be found in README.md // const string filterIdleSamplesQuery = "[IP]:=\"native_safe_halt\""; var utilByCpuStackConfig = new TableConfiguration("Utilization by CPU, Stack") { Columns = new[] { cpuColumn, callStackColumn, TableConfiguration.PivotColumn, processColumn, threadIdColumn, instructionPointerColumn, instructionPointerModuleColumn, sampleNumberColumn, timestampDateTimeColumn, timestampColumn, weightColumn, countColumn, TableConfiguration.GraphColumn, weightPctColumn }, InitialFilterShouldKeep = false, InitialFilterQuery = filterIdleSamplesQuery, }; utilByCpuStackConfig.AddColumnRole(ColumnRole.EndTime, timestampColumn); utilByCpuStackConfig.AddColumnRole(ColumnRole.Duration, weightColumn); utilByCpuStackConfig.AddColumnRole(ColumnRole.ResourceId, cpuColumn); var utilByCpuConfig = new TableConfiguration("Utilization by CPU") { Columns = new[] { cpuColumn, TableConfiguration.PivotColumn, countColumn, callStackColumn, processColumn, threadIdColumn, instructionPointerColumn, instructionPointerModuleColumn, sampleNumberColumn, timestampDateTimeColumn, timestampColumn, weightColumn, TableConfiguration.GraphColumn, weightPctColumn }, InitialFilterShouldKeep = false, InitialFilterQuery = filterIdleSamplesQuery, }; utilByCpuConfig.AddColumnRole(ColumnRole.EndTime, timestampColumn); utilByCpuConfig.AddColumnRole(ColumnRole.Duration, weightColumn); utilByCpuConfig.AddColumnRole(ColumnRole.ResourceId, cpuColumn); var utilByProcessConfig = new TableConfiguration("Utilization by Process") { Columns = new[] { processColumn, TableConfiguration.PivotColumn, countColumn, callStackColumn, cpuColumn, threadIdColumn, instructionPointerColumn, instructionPointerModuleColumn, sampleNumberColumn, timestampDateTimeColumn, timestampColumn, weightColumn, TableConfiguration.GraphColumn, weightPctColumn }, InitialFilterShouldKeep = false, InitialFilterQuery = filterIdleSamplesQuery, }; utilByProcessConfig.AddColumnRole(ColumnRole.EndTime, timestampColumn); utilByProcessConfig.AddColumnRole(ColumnRole.Duration, weightColumn); utilByProcessConfig.AddColumnRole(ColumnRole.ResourceId, cpuColumn); var utilByProcessStackConfig = new TableConfiguration("Utilization by Process, Stack") { Columns = new[] { processColumn, callStackColumn, TableConfiguration.PivotColumn, countColumn, cpuColumn, threadIdColumn, instructionPointerColumn, instructionPointerModuleColumn, sampleNumberColumn, timestampDateTimeColumn, timestampColumn, weightColumn, TableConfiguration.GraphColumn, weightPctColumn }, InitialFilterShouldKeep = false, InitialFilterQuery = filterIdleSamplesQuery, }; utilByProcessStackConfig.AddColumnRole(ColumnRole.EndTime, timestampColumn); utilByProcessStackConfig.AddColumnRole(ColumnRole.Duration, weightColumn); utilByProcessStackConfig.AddColumnRole(ColumnRole.ResourceId, cpuColumn); var flameByProcessStackConfig = new TableConfiguration("Flame by Process, Stack") { Columns = new[] { processColumn, callStackColumn, TableConfiguration.PivotColumn, countColumn, cpuColumn, threadIdColumn, instructionPointerColumn, instructionPointerModuleColumn, sampleNumberColumn, timestampDateTimeColumn, timestampColumn, weightColumn, TableConfiguration.GraphColumn, weightPctColumn }, ChartType = ChartType.Flame, InitialFilterShouldKeep = false, InitialFilterQuery = filterIdleSamplesQuery, }; flameByProcessStackConfig.AddColumnRole(ColumnRole.EndTime, timestampColumn); flameByProcessStackConfig.AddColumnRole(ColumnRole.Duration, weightColumn); flameByProcessStackConfig.AddColumnRole(ColumnRole.ResourceId, cpuColumn); // // // Use the table builder to build the table. // Add and set table configuration if applicable. // Then set the row count (we have one row per file) and then add the columns using AddColumn. // var table = tableBuilder .AddTableConfiguration(utilByCpuStackConfig) .SetDefaultTableConfiguration(utilByCpuStackConfig) .AddTableConfiguration(utilByCpuConfig) .AddTableConfiguration(utilByProcessConfig) .AddTableConfiguration(utilByProcessStackConfig) .AddTableConfiguration(flameByProcessStackConfig) .SetRowCount(firstPerfDataTxtLogParsed.SampleIndexLimit) .AddColumn(sampleNumberColumn, sampleIndex) .AddColumn(timestampColumn, timeStampProjection) .AddColumn(instructionPointerColumn, ipStackFrameProjection) .AddColumn(instructionPointerModuleColumn, ipModuleProjection) .AddColumn(countColumn, countProjection) .AddColumn(weightColumn, weightProj) .AddColumn(threadIdColumn, threadIdProjection) .AddColumn(processColumn, processProjection) .AddColumn(weightPctColumn, weightPercentProj) .AddColumn(startTimeCol, timeStampStartProjection) .AddColumn(viewportClippedStartTimeCol, viewportClippedStartTimeProj) .AddColumn(viewportClippedEndTimeCol, viewportClippedEndTimeProj) .AddColumn(clippedWeightCol, clippedWeightProj) .AddColumn(cpuColumn, cpuProjection) ; table.AddHierarchicalColumn(callStackColumn, baseProjection.Compose((i) => GetCallStack(i, firstPerfDataTxtLogParsed)), new ArrayAccessProvider <string>()); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { var pathIdentifier = DataOutputPath.ForSource(PerfConstants.SourceId, PerfCpuClockDataCooker.Identifier, nameof(PerfCpuClockDataCooker.CpuClockEvents)); var cpuClocks = tableData.QueryOutput <IReadOnlyList <ICpuClockEvent> >(pathIdentifier); if (cpuClocks.Count == 0) { return; } var config = new TableConfiguration("CPU Utilization") { Columns = new[] { cpuColumn, callStackColumn, TableConfiguration.PivotColumn, pidColumn, threadIdColumn, ipColumn, symbolTypeColumn, ipSymbolColumn, idColumn, weightColumn, countColumn, timeStampColumn, TableConfiguration.GraphColumn, weightPctColumn }, }; config.AddColumnRole(ColumnRole.EndTime, timeStampColumn); config.AddColumnRole(ColumnRole.Duration, weightColumn); config.AddColumnRole(ColumnRole.ResourceId, cpuColumn); var table = tableBuilder.AddTableConfiguration(config) .SetDefaultTableConfiguration(config) .SetRowCount(cpuClocks.Count); var timeStampProjection = Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Timestamp); table.AddColumn(cpuColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Cpu)); table.AddColumn(ipColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Ip)); table.AddColumn(symbolTypeColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Ip_Symbol?.SymbolType?.SymbolTypeDescription.SymbolTypeShortName)); table.AddColumn(ipSymbolColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Ip_Symbol?.Name)); table.AddColumn(threadIdColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Tid)); table.AddColumn(pidColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Pid)); table.AddColumn(idColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Id)); table.AddColumn(perfPeriodColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Perf_Period)); table.AddColumn(perfCallchainSizeColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Perf_Callchain_Size)); table.AddHierarchicalColumn(callStackColumn, Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].CallStack), new ArrayAccessProvider <string>()); table.AddColumn(timeStampColumn, timeStampProjection); var oneMsSample = new TimestampDelta(1000000); // 1ms for now until we can figure out weight better var oneNs = new TimestampDelta(1); var weightProj = Projection.Constant(oneMsSample); var timeStampStartProjection = Projection.CreateUsingFuncAdaptor((i) => cpuClocks[i].Timestamp - oneNs); // We will say sample lasted 1ns IProjection <int, Timestamp> viewportClippedStartTimeProj = Projection.ClipTimeToVisibleDomain.Create(timeStampStartProjection); IProjection <int, Timestamp> viewportClippedEndTimeProj = Projection.ClipTimeToVisibleDomain.Create(timeStampProjection); IProjection <int, TimestampDelta> clippedWeightProj = Projection.Select( viewportClippedEndTimeProj, viewportClippedStartTimeProj, new ReduceTimeSinceLastDiff()); IProjection <int, double> weightPercentProj = Projection.VisibleDomainRelativePercent.Create(clippedWeightProj); IProjection <int, int> countProj = SequentialGenerator.Create( cpuClocks.Count, Projection.Constant(1), Projection.Constant(0)); table.AddColumn(weightColumn, weightProj); table.AddColumn(countColumn, countProj); table.AddColumn(weightPctColumn, weightPercentProj); table.AddColumn(startTimeCol, timeStampStartProjection); table.AddColumn(viewportClippedStartTimeCol, viewportClippedStartTimeProj); table.AddColumn(viewportClippedEndTimeCol, viewportClippedEndTimeProj); table.AddColumn(clippedWeightCol, clippedWeightProj); }