public void MonitorGarbageCollections() { string[] compactingGcTags = { "compacting_gc:true" }; var statsd = new Mock <IDogStatsd>(); var mutex = new ManualResetEventSlim(); // GcPauseTime is pushed on the GcRestartEnd event, which should be the last event for any GC statsd.Setup(s => s.Timer(MetricsNames.GcPauseTime, It.IsAny <double>(), It.IsAny <double>(), null)) .Callback(() => mutex.Set()); using var listener = new RuntimeEventListener(statsd.Object); statsd.ResetCalls(); for (int i = 0; i < 3; i++) { mutex.Reset(); // In case a GC was triggered when creating the listener GC.Collect(2, GCCollectionMode.Forced, blocking: true, compacting: true); // GC events are pushed asynchronously, wait for the last one to be processed mutex.Wait(); } statsd.Verify(s => s.Gauge(MetricsNames.Gen0HeapSize, It.IsAny <ulong>(), It.IsAny <double>(), null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.Gen1HeapSize, It.IsAny <ulong>(), It.IsAny <double>(), null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.Gen2HeapSize, It.IsAny <ulong>(), It.IsAny <double>(), null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.LohSize, It.IsAny <ulong>(), It.IsAny <double>(), null), Times.AtLeastOnce); statsd.Verify(s => s.Timer(MetricsNames.GcPauseTime, It.IsAny <double>(), It.IsAny <double>(), null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.GcMemoryLoad, It.IsAny <uint>(), It.IsAny <double>(), null), Times.AtLeastOnce); statsd.Verify(s => s.Increment(MetricsNames.Gen2CollectionsCount, 1, It.IsAny <double>(), compactingGcTags), Times.AtLeastOnce); }
public void PushEvents() { var statsd = new Mock <IDogStatsd>(); using var listener = new RuntimeEventListener(statsd.Object); listener.Refresh(); statsd.Verify(s => s.Gauge(MetricsNames.ContentionTime, It.IsAny <double>(), 1, null), Times.Once); statsd.Verify(s => s.Counter(MetricsNames.ContentionCount, It.IsAny <long>(), 1, null), Times.Once); statsd.Verify(s => s.Gauge(MetricsNames.ThreadPoolWorkersCount, It.IsAny <int>(), 1, null), Times.Once); }
public void PushEventCounters() { // Pretending we're aspnetcore var eventSource = new EventSource("Microsoft.AspNetCore.Hosting"); var mutex = new ManualResetEventSlim(); Func <double> callback = () => { mutex.Set(); return(0.0); }; var counters = new List <DiagnosticCounter> { new PollingCounter("current-requests", eventSource, () => 1.0), new PollingCounter("failed-requests", eventSource, () => 2.0), new PollingCounter("total-requests", eventSource, () => 4.0), new PollingCounter("request-queue-length", eventSource, () => 8.0), new PollingCounter("connection-queue-length", eventSource, () => 16.0), new PollingCounter("total-connections", eventSource, () => 32.0), // This counter sets the mutex, so it needs to be created last new PollingCounter("Dummy", eventSource, callback) }; var statsd = new Mock <IDogStatsd>(); using var listener = new RuntimeEventListener(statsd.Object, TimeSpan.FromSeconds(1)); // Wait for the counters to be refreshed mutex.Wait(); #if NETCOREAPP3_1 // Reduce the probability of a crash on .NET Core 3.1.9/3.1.10: https://github.com/dotnet/coreclr/pull/28112/ // The crash happens if disposing counters while they're being refreshed. // Since the mutex is set when refreshing the counters, there's a high probability for the disposing to occur concurrently. // The small pause should help de-syncing the two operations. Thread.Sleep(100); #endif statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreCurrentRequests, 1.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreFailedRequests, 2.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreTotalRequests, 4.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreRequestQueueLength, 8.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreConnectionQueueLength, 16.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreTotalConnections, 32.0, 1, null), Times.AtLeastOnce); foreach (var counter in counters) { counter.Dispose(); } }
public void PushEventCounters() { // Pretending we're aspnetcore var eventSource = new EventSource("Microsoft.AspNetCore.Hosting"); var mutex = new ManualResetEventSlim(); Func <double> callback = () => { mutex.Set(); return(0.0); }; var counters = new List <DiagnosticCounter> { new PollingCounter("current-requests", eventSource, () => 1.0), new PollingCounter("failed-requests", eventSource, () => 2.0), new PollingCounter("total-requests", eventSource, () => 4.0), new PollingCounter("request-queue-length", eventSource, () => 8.0), new PollingCounter("connection-queue-length", eventSource, () => 16.0), new PollingCounter("total-connections", eventSource, () => 32.0), // This counter sets the mutex, so it needs to be created last new PollingCounter("Dummy", eventSource, callback) }; var statsd = new Mock <IDogStatsd>(); using var listener = new RuntimeEventListener(statsd.Object, TimeSpan.FromSeconds(1)); // Wait for the counters to be refreshed mutex.Wait(); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreCurrentRequests, 1.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreFailedRequests, 2.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreTotalRequests, 4.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreRequestQueueLength, 8.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreConnectionQueueLength, 16.0, 1, null), Times.AtLeastOnce); statsd.Verify(s => s.Gauge(MetricsNames.AspNetCoreTotalConnections, 32.0, 1, null), Times.AtLeastOnce); foreach (var counter in counters) { counter.Dispose(); } }
static void Main(string[] args) { Options options = null; RuntimeEventListener eventListener = null; Parser.Default.ParseArguments <Options>(args) .WithParsed(_options => { options = _options; }); if (options == null) { return; } if (options.Verbose) { eventListener = new RuntimeEventListener(); } IPAddress address = IPAddress.Parse(options.Address); IPEndPoint endpoint = new IPEndPoint(address, options.Port); switch (options.testType) { case TestType.Pipeline: { PipeEchoServer server = new PipeEchoServer(); server.Listen(endpoint, listenBacklog: 5000); } break; case TestType.TcpSocket: { TcpEchoServer server = new TcpEchoServer(); server.Listen(endpoint, 5000); } break; } Console.WriteLine("enter return to exit"); Console.ReadLine(); }
static void Main(string[] args) { Options options = null; RuntimeEventListener listener = null; Parser.Default.ParseArguments <Options>(args) .WithParsed(_options => { options = _options; }); if (options == null) { return; } if (options.Verbose) { listener = new RuntimeEventListener(); } EchoClient[] clients = new EchoClient[options.Clients]; Task[] echoTasks = new Task[options.Clients]; Random r = new Random(); byte[] payload = new byte[options.Payload]; r.NextBytes(payload); IPAddress address = IPAddress.Parse(options.Address); EndPoint endpoint = new IPEndPoint(address, options.Port); if (options.WarnupRound > 0) { Task[] warnupTask = new Task[options.WarnupRound]; for (int i = 0; i < options.WarnupRound; i++) { EchoClient client = new EchoClient(endpoint, options.Rounds, payload); warnupTask[i] = client.Start(options.TransportType); } Task.WaitAll(warnupTask); } for (int i = 0; i < options.Clients; i++) { clients[i] = new EchoClient(endpoint, options.Rounds, payload); } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); if (listener != null) { listener.ThreadPoolWorkerThreadWait += () => { Console.WriteLine("==============> eq:{0} dq:{1} cnnBegin:{2} cnnFinish:{3} writeBegin:{4} writeFinish:{5} readFinish{6} {7}ms", Interlocked.Read(ref RuntimeEventListener.s_enqueueCnt), Interlocked.Read(ref RuntimeEventListener.s_dequeueCnt), Interlocked.Read(ref EchoClient.s_connectBeginCnt), Interlocked.Read(ref EchoClient.s_connectFinishCnt), Interlocked.Read(ref EchoClient.s_writeBeginCnt), Interlocked.Read(ref EchoClient.s_writeBeginCnt), Interlocked.Read(ref EchoClient.s_readFinishCnt), stopwatch.ElapsedMilliseconds ); }; } for (int i = 0; i < options.Clients; i++) { echoTasks[i] = clients[i].Start(options.TransportType); } Task.WaitAll(echoTasks); stopwatch.Stop(); int errorNum = 0; foreach (EchoClient cli in clients) { if (cli.Error != null) { errorNum++; } } Console.WriteLine($"{options.Clients} clients, payload {options.Payload} bytes, {options.Rounds} rounds"); Console.WriteLine("Total Time Elapsed: {0} Milliseconds", stopwatch.Elapsed.TotalMilliseconds); Console.WriteLine("{0} error of {1}", errorNum, options.Clients); double[] connect = clients.Where(cli => cli.Error == null).Select(cli => cli.ConnectDuration.TotalMilliseconds).ToArray(); double[] echo = clients.Where(cli => cli.Error == null).Select(cli => cli.EchoDuration.TotalMilliseconds).ToArray(); double[] total = clients.Where(cli => cli.Error == null).Select(cli => cli.ConnectDuration.TotalMilliseconds + cli.EchoDuration.TotalMilliseconds).ToArray(); Console.WriteLine("connect\tp90:{0:N2}ms\tp95:{1:N2}ms\tp99:{2:N2}ms\tp99.9:{3:N2}ms", Percentile(connect, 0.9), Percentile(connect, 0.95), Percentile(connect, 0.99), Percentile(connect, 0.999)); Console.WriteLine("echo\tp90:{0:N2}ms\tp95:{1:N2}ms\tp99:{2:N2}ms\tp99.9:{3:N2}ms", Percentile(echo, 0.9), Percentile(echo, 0.95), Percentile(echo, 0.99), Percentile(echo, 0.999)); Console.WriteLine("total\tp90:{0:N2}ms\tp95:{1:N2}ms\tp99:{2:N2}ms\tp99.9:{3:N2}ms", Percentile(total, 0.9), Percentile(total, 0.95), Percentile(total, 0.99), Percentile(total, 0.999)); Console.WriteLine("==============> eq:{0} dq:{1} cnnBegin:{2} cnnFinish:{3} writeBegin:{4} writeFinish:{5} readFinish{6} {7}ms", Interlocked.Read(ref RuntimeEventListener.s_enqueueCnt), Interlocked.Read(ref RuntimeEventListener.s_dequeueCnt), Interlocked.Read(ref EchoClient.s_connectBeginCnt), Interlocked.Read(ref EchoClient.s_connectFinishCnt), Interlocked.Read(ref EchoClient.s_writeBeginCnt), Interlocked.Read(ref EchoClient.s_writeBeginCnt), Interlocked.Read(ref EchoClient.s_readFinishCnt), stopwatch.ElapsedMilliseconds ); }