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
10 changes: 5 additions & 5 deletions Dashboard/Controls/PlanViewerControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -688,17 +688,17 @@ private void ShowPropertiesPanel(PlanNode node)

// Timing
if (node.ActualElapsedMs > 0 || node.ActualCPUMs > 0
|| node.UdfCpuTimeUs > 0 || node.UdfElapsedTimeUs > 0)
|| node.UdfCpuTimeMs > 0 || node.UdfElapsedTimeMs > 0)
{
AddPropertySection("Actual Timing");
if (node.ActualElapsedMs > 0)
AddPropertyRow("Elapsed Time", $"{node.ActualElapsedMs:N0} ms");
if (node.ActualCPUMs > 0)
AddPropertyRow("CPU Time", $"{node.ActualCPUMs:N0} ms");
if (node.UdfElapsedTimeUs > 0)
AddPropertyRow("UDF Elapsed", $"{node.UdfElapsedTimeUs:N0} us");
if (node.UdfCpuTimeUs > 0)
AddPropertyRow("UDF CPU", $"{node.UdfCpuTimeUs:N0} us");
if (node.UdfElapsedTimeMs > 0)
AddPropertyRow("UDF Elapsed", $"{node.UdfElapsedTimeMs:N0} ms");
if (node.UdfCpuTimeMs > 0)
AddPropertyRow("UDF CPU", $"{node.UdfCpuTimeMs:N0} ms");
}

// I/O
Expand Down
4 changes: 2 additions & 2 deletions Dashboard/Models/PlanModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ public class PlanNode
public string? ActionColumn { get; set; }
public long ActualSegmentReads { get; set; }
public long ActualSegmentSkips { get; set; }
public long UdfCpuTimeUs { get; set; }
public long UdfElapsedTimeUs { get; set; }
public long UdfCpuTimeMs { get; set; }
public long UdfElapsedTimeMs { get; set; }

// XSD gap: RelOp-level metadata
public bool GroupExecuted { get; set; }
Expand Down
8 changes: 3 additions & 5 deletions Dashboard/Services/PlanAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,13 @@
}

// Rule 4: UDF timing — any node spending time in UDFs (actual plans)
if (node.UdfCpuTimeUs > 0 || node.UdfElapsedTimeUs > 0)
if (node.UdfCpuTimeMs > 0 || node.UdfElapsedTimeMs > 0)
{
var cpuMs = node.UdfCpuTimeUs / 1000.0;
var elapsedMs = node.UdfElapsedTimeUs / 1000.0;
node.Warnings.Add(new PlanWarning
{
WarningType = "UDF Execution",
Message = $"Scalar UDF executing on this operator. UDF elapsed: {elapsedMs:F1}ms, UDF CPU: {cpuMs:F1}ms",
Severity = elapsedMs >= 1000 ? PlanWarningSeverity.Critical : PlanWarningSeverity.Warning
Message = $"Scalar UDF executing on this operator. UDF elapsed: {node.UdfElapsedTimeMs:N0}ms, UDF CPU: {node.UdfCpuTimeMs:N0}ms",
Severity = node.UdfElapsedTimeMs >= 1000 ? PlanWarningSeverity.Critical : PlanWarningSeverity.Warning
});
}

Expand Down Expand Up @@ -440,7 +438,7 @@

// Rule 22: Table variables (Object name starts with @)
if (!string.IsNullOrEmpty(node.ObjectName) &&
node.ObjectName.Contains("@"))

Check warning on line 441 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 441 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 441 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 441 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 441 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 441 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -574,7 +572,7 @@
var refPattern = new Regex(
$@"\b(FROM|JOIN)\s+{Regex.Escape(cteName)}\b",
RegexOptions.IgnoreCase);
var refCount = refPattern.Matches(text).Count;

Check warning on line 575 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'Regex.Count' instead of 'Regex.Matches(...).Count' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1875)

Check warning on line 575 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'Regex.Count' instead of 'Regex.Matches(...).Count' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1875)

Check warning on line 575 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'Regex.Count' instead of 'Regex.Matches(...).Count' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1875)

Check warning on line 575 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'Regex.Count' instead of 'Regex.Matches(...).Count' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1875)

Check warning on line 575 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'Regex.Count' instead of 'Regex.Matches(...).Count' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1875)

Check warning on line 575 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'Regex.Count' instead of 'Regex.Matches(...).Count' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1875)

if (refCount > 1)
{
Expand Down
4 changes: 2 additions & 2 deletions Dashboard/Services/ShowPlanParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1179,8 +1179,8 @@ private static PlanNode ParseRelOp(XElement relOpEl)
node.ActualExecutionMode = actualExecMode;
node.ActualSegmentReads = totalSegmentReads;
node.ActualSegmentSkips = totalSegmentSkips;
node.UdfCpuTimeUs = totalUdfCpu;
node.UdfElapsedTimeUs = maxUdfElapsed;
node.UdfCpuTimeMs = totalUdfCpu;
node.UdfElapsedTimeMs = maxUdfElapsed;

// Store per-thread data for parallel skew analysis
foreach (var thread in runtimeEl.Elements(Ns + "RunTimeCountersPerThread"))
Expand Down
10 changes: 5 additions & 5 deletions Lite/Controls/PlanViewerControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -698,17 +698,17 @@ private void ShowPropertiesPanel(PlanNode node)

// Timing
if (node.ActualElapsedMs > 0 || node.ActualCPUMs > 0
|| node.UdfCpuTimeUs > 0 || node.UdfElapsedTimeUs > 0)
|| node.UdfCpuTimeMs > 0 || node.UdfElapsedTimeMs > 0)
{
AddPropertySection("Actual Timing");
if (node.ActualElapsedMs > 0)
AddPropertyRow("Elapsed Time", $"{node.ActualElapsedMs:N0} ms");
if (node.ActualCPUMs > 0)
AddPropertyRow("CPU Time", $"{node.ActualCPUMs:N0} ms");
if (node.UdfElapsedTimeUs > 0)
AddPropertyRow("UDF Elapsed", $"{node.UdfElapsedTimeUs:N0} us");
if (node.UdfCpuTimeUs > 0)
AddPropertyRow("UDF CPU", $"{node.UdfCpuTimeUs:N0} us");
if (node.UdfElapsedTimeMs > 0)
AddPropertyRow("UDF Elapsed", $"{node.UdfElapsedTimeMs:N0} ms");
if (node.UdfCpuTimeMs > 0)
AddPropertyRow("UDF CPU", $"{node.UdfCpuTimeMs:N0} ms");
}

// I/O
Expand Down
4 changes: 2 additions & 2 deletions Lite/Models/PlanModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ public class PlanNode
public string? ActionColumn { get; set; }
public long ActualSegmentReads { get; set; }
public long ActualSegmentSkips { get; set; }
public long UdfCpuTimeUs { get; set; }
public long UdfElapsedTimeUs { get; set; }
public long UdfCpuTimeMs { get; set; }
public long UdfElapsedTimeMs { get; set; }

// XSD gap: RelOp-level metadata
public bool GroupExecuted { get; set; }
Expand Down
8 changes: 3 additions & 5 deletions Lite/Services/PlanAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,13 @@ private static void AnalyzeNode(PlanNode node, PlanStatement stmt)
}

// Rule 4: UDF timing — any node spending time in UDFs (actual plans)
if (node.UdfCpuTimeUs > 0 || node.UdfElapsedTimeUs > 0)
if (node.UdfCpuTimeMs > 0 || node.UdfElapsedTimeMs > 0)
{
var cpuMs = node.UdfCpuTimeUs / 1000.0;
var elapsedMs = node.UdfElapsedTimeUs / 1000.0;
node.Warnings.Add(new PlanWarning
{
WarningType = "UDF Execution",
Message = $"Scalar UDF executing on this operator. UDF elapsed: {elapsedMs:F1}ms, UDF CPU: {cpuMs:F1}ms",
Severity = elapsedMs >= 1000 ? PlanWarningSeverity.Critical : PlanWarningSeverity.Warning
Message = $"Scalar UDF executing on this operator. UDF elapsed: {node.UdfElapsedTimeMs:N0}ms, UDF CPU: {node.UdfCpuTimeMs:N0}ms",
Severity = node.UdfElapsedTimeMs >= 1000 ? PlanWarningSeverity.Critical : PlanWarningSeverity.Warning
});
}

Expand Down
4 changes: 2 additions & 2 deletions Lite/Services/ShowPlanParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1179,8 +1179,8 @@ private static PlanNode ParseRelOp(XElement relOpEl)
node.ActualExecutionMode = actualExecMode;
node.ActualSegmentReads = totalSegmentReads;
node.ActualSegmentSkips = totalSegmentSkips;
node.UdfCpuTimeUs = totalUdfCpu;
node.UdfElapsedTimeUs = maxUdfElapsed;
node.UdfCpuTimeMs = totalUdfCpu;
node.UdfElapsedTimeMs = maxUdfElapsed;

// Store per-thread data for parallel skew analysis
foreach (var thread in runtimeEl.Elements(Ns + "RunTimeCountersPerThread"))
Expand Down
Loading