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
18 changes: 12 additions & 6 deletions src/PlanViewer.Core/Services/ShowPlanParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1665,20 +1665,26 @@ private static List<PlanWarning> ParseWarningsFromElement(XElement warningsEl)
});
}

// Memory grant warning
// Memory grant warning (from plan XML) — gate at 1 GB to avoid noise on small grants
// All values are in KB, consistent with MemoryGrantInfo element
var memWarnEl = warningsEl.Element(Ns + "MemoryGrantWarning");
if (memWarnEl != null)
{
var kind = memWarnEl.Attribute("GrantWarningKind")?.Value ?? "Unknown";
var requested = ParseLong(memWarnEl.Attribute("RequestedMemory")?.Value);
var granted = ParseLong(memWarnEl.Attribute("GrantedMemory")?.Value);
var maxUsed = ParseLong(memWarnEl.Attribute("MaxUsedMemory")?.Value);
result.Add(new PlanWarning
if (granted >= 1048576) // 1 GB in KB
{
WarningType = "Memory Grant",
Message = $"{kind}: Requested {requested:N0} KB, Granted {granted:N0} KB, Used {maxUsed:N0} KB",
Severity = PlanWarningSeverity.Warning
});
var grantedMB = granted / 1024.0;
var usedMB = maxUsed / 1024.0;
result.Add(new PlanWarning
{
WarningType = "Memory Grant",
Message = $"{kind}: Granted {grantedMB:N0} MB, Used {usedMB:N0} MB",
Severity = PlanWarningSeverity.Warning
});
}
}

// Implicit conversions
Expand Down
9 changes: 5 additions & 4 deletions tests/PlanViewer.Core.Tests/PlanAnalyzerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,15 @@ public void Rule08_ParallelSkew_DetectedOnHighRowScan()
// ---------------------------------------------------------------

[Fact]
public void Rule09a_ExcessiveMemoryGrant_DetectedInLazySpoolPlan()
public void Rule09a_ExcessiveMemoryGrant_SmallGrantSuppressed()
{
// lazy_spool_plan has a 1 MB grant — well under the 1 GB threshold.
// The XML MemoryGrantWarning should be suppressed (not worth surfacing).
var plan = PlanTestHelper.LoadAndAnalyze("lazy_spool_plan.sqlplan");
// The parser may surface this as a plan-level warning from XML
var allWarnings = PlanTestHelper.AllWarnings(plan);

Assert.Contains(allWarnings, w =>
w.WarningType.Contains("Memory Grant") || w.WarningType == "Excessive Memory Grant");
Assert.DoesNotContain(allWarnings, w =>
w.WarningType == "Memory Grant");
}

// ---------------------------------------------------------------
Expand Down
Loading