我有一个程序集,它监视在机器上运行的许多微服务的性能统计信息。代码使用性能计数器来获取和发布数据,如下所示:
_counters = new Dictionary<string, PerformanceCounter>
{
["System Memory Available Bytes"] = new PerformanceCounter { CategoryName = "Memory", CounterName = "Available Bytes", ReadOnly = true },
["System CPU Usage %"] = new PerformanceCounter { CategoryName = "Processor", CounterName = "% Processor Time", InstanceName = "_Total", ReadOnly = true },
["Process CPU Usage %"] = new PerformanceCounter { CategoryName = "Process", CounterName = "% Processor Time", InstanceName = processName, ReadOnly = true },
["Process Thread Count"] = new PerformanceCounter { CategoryName = "Process", CounterName = "Thread Count", InstanceName = processName, ReadOnly = true },
["Process Private Bytes"] = new PerformanceCounter { CategoryName = "Process", CounterName = "Private Bytes", InstanceName = processName, ReadOnly = true },
["Process Working Set Bytes"] = new PerformanceCounter { CategoryName = "Process", CounterName = "Working Set", InstanceName = processName, ReadOnly = true },
["Process Virtual Bytes"] = new PerformanceCounter { CategoryName = "Process", CounterName = "Virtual Bytes", InstanceName = processName, ReadOnly = true },
["Contention Rate/Sec"] = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "Contention Rate / Sec", InstanceName = processName, ReadOnly = true },
["Contention Queue Peak Size"] = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "Queue Length Peak", InstanceName = processName, ReadOnly = true },
["Contention Total Count"] = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "Total # of Contentions", InstanceName = processName, ReadOnly = true },
["Induced GC Count"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "# Induced GC", InstanceName = processName, ReadOnly = true },
["GC Handle Count"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "# GC Handles", InstanceName = processName, ReadOnly = true },
["Finalization Survivors"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "Finalization Survivors", InstanceName = processName, ReadOnly = true },
["LOB Size Bytes"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "Large Object Heap size", InstanceName = processName, ReadOnly = true },
["Total Bytes in all Heaps"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "# Bytes in all Heaps", InstanceName = processName, ReadOnly = true },
["Total Bytes Committed"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "# Total committed Bytes", InstanceName = processName, ReadOnly = true },
["Total Bytes Reserved"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "# Total reserved Bytes", InstanceName = processName, ReadOnly = true },
["Time in GC %"] = new PerformanceCounter { CategoryName = ".NET CLR Memory", CounterName = "% Time in GC", InstanceName = processName, ReadOnly = true },
["Time in JIT %"] = new PerformanceCounter { CategoryName = ".NET CLR Jit", CounterName = "% Time in Jit", InstanceName = processName, ReadOnly = true },
};
// Make sure we read each counter once, this is to set the sample start for
// some of the counters that need a start, end invocation to return a value.
foreach (var counter in _counters.Values) { counter.NextValue(); }
然后我启动一个计时器,每隔 1 秒发布数据(为了简洁,我只将它们存储在变量中):
_timer = new Timer(1000);
_timer.Elapsed += OnTimerElapsed;
_timer.Start();
private void OnTimerElapsed(object sender, ElapsedEventArgs eArgs)
{
var a = _counters["System CPU Usage %"].NextValue();
var b = _counters["System Memory Available Bytes"].NextValue();
//var c = _counters["Process CPU Usage %"].NextValue()/Environment.ProcessorCount;
//var d = _counters["Process Thread Count"].NextValue();
//var e = _counters["Process Private Bytes"].NextValue();
//var f = _counters["Process Working Set Bytes"].NextValue();
//var g = _counters["Process Virtual Bytes"].NextValue();
var h = _counters["Contention Rate/Sec"].NextValue();
var i = _counters["Contention Queue Peak Size"].NextValue();
var j = _counters["Contention Total Count"].NextValue();
var k = _counters["Induced GC Count"].NextValue();
var l = _counters["GC Handle Count"].NextValue();
var m = _counters["Finalization Survivors"].NextValue();
var n = _counters["LOB Size Bytes"].NextValue();
var o = _counters["Total Bytes in all Heaps"].NextValue();
var p = _counters["Total Bytes Committed"].NextValue();
var q = _counters["Total Bytes Reserved"].NextValue();
var r = _counters["Time in GC %"].NextValue();
var s = _counters["Time in JIT %"].NextValue();
}
使用注释计数器运行程序集会导致预期的GC
行为,每隔几秒只会收集gen 0
个集合。但是,如果我将<{1}}中的任何计数器取消注释为c
,那么我将获得一个完整的(g
到gen 0
)集合 1 秒。我无法解释这种行为,发生了什么?