diff --git a/src/PlanViewer.Core/Services/ShowPlanParser.cs b/src/PlanViewer.Core/Services/ShowPlanParser.cs index 5cf9f11..62ebf42 100644 --- a/src/PlanViewer.Core/Services/ShowPlanParser.cs +++ b/src/PlanViewer.Core/Services/ShowPlanParser.cs @@ -1665,7 +1665,8 @@ private static List 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) { @@ -1673,12 +1674,17 @@ private static List ParseWarningsFromElement(XElement warningsEl) 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 diff --git a/tests/PlanViewer.Core.Tests/PlanAnalyzerTests.cs b/tests/PlanViewer.Core.Tests/PlanAnalyzerTests.cs index 28ad002..33d0689 100644 --- a/tests/PlanViewer.Core.Tests/PlanAnalyzerTests.cs +++ b/tests/PlanViewer.Core.Tests/PlanAnalyzerTests.cs @@ -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"); } // ---------------------------------------------------------------