From 3b5dbd41c68dc95bc0914888f055b6b572bca660 Mon Sep 17 00:00:00 2001 From: Cristian Pop Date: Tue, 17 Sep 2019 16:01:42 -0700 Subject: [PATCH 1/2] Stress test fixes --- e2e/stress/IoTClientPerf/IoTClientPerf.csproj | 2 +- e2e/stress/IoTClientPerf/PerfTestRunner.cs | 16 +-- .../Properties/launchSettings.json | 2 +- .../IoTClientPerf/Reporting/ResultWriter.cs | 5 + .../Reporting/ResultWriterFile.cs | 2 +- .../IoTClientPerf/Reporting/SystemMetrics.cs | 47 +++++--- .../Reporting/TelemetryMetrics.cs | 15 ++- .../Scenarios/DeviceAllNoRetry.cs | 40 ++++++- .../Scenarios/DeviceC2DNoRetry.cs | 2 +- .../Scenarios/DeviceClientScenario.cs | 104 ++++++++++-------- .../Scenarios/DeviceD2CNoRetry.cs | 2 +- .../Scenarios/DeviceMethodsNoRetry.cs | 2 +- .../Scenarios/DeviceOneD2CTest.cs | 8 +- .../Scenarios/HarnessBaseline.cs | 6 +- .../Scenarios/ServiceClientScenarios.cs | 51 +++++++-- .../IoTClientPerf/scripts/runClient.ps1 | 23 +++- .../IoTClientPerf/scripts/runServer.ps1 | 21 +++- 17 files changed, 232 insertions(+), 116 deletions(-) diff --git a/e2e/stress/IoTClientPerf/IoTClientPerf.csproj b/e2e/stress/IoTClientPerf/IoTClientPerf.csproj index 42a9626332..6b9c603b6f 100644 --- a/e2e/stress/IoTClientPerf/IoTClientPerf.csproj +++ b/e2e/stress/IoTClientPerf/IoTClientPerf.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.1 + netcoreapp2.2 Microsoft.Azure.Devices.E2ETests diff --git a/e2e/stress/IoTClientPerf/PerfTestRunner.cs b/e2e/stress/IoTClientPerf/PerfTestRunner.cs index eba9b2e218..e58dcd1ba4 100644 --- a/e2e/stress/IoTClientPerf/PerfTestRunner.cs +++ b/e2e/stress/IoTClientPerf/PerfTestRunner.cs @@ -25,8 +25,8 @@ public class PerfTestRunner private readonly int _timeSeconds; private readonly Func _scenarioFactory; - private PerfScenario[] _tests; - private Stopwatch _sw = new Stopwatch(); + private readonly PerfScenario[] _tests; + private readonly Stopwatch _sw = new Stopwatch(); public PerfTestRunner( ResultWriter writer, @@ -148,13 +148,13 @@ private async Task LoopAsync() (double avgRps, double stdDevRps) = CalculateAvgAndStDev(statRps); double avgBps = avgRps * _messageSizeBytes; double stdDevBps = stdDevRps * _messageSizeBytes; - SystemMetrics.GetMetrics(out int cpuPercent, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); + SystemMetrics.GetMetrics(out int cpuLoad, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); Console.WriteLine($"[{_sw.Elapsed}] Loop Statistics:"); Console.WriteLine($"RPS : {requestsPerSec,10:N2} R/s Avg: {avgRps,10:N2} R/s +/-StdDev: {stdDevRps,10:N2} R/s"); Console.WriteLine($"Throughput: {GetHumanReadableBytes(transferPerSec)}/s Avg: {GetHumanReadableBytes(avgBps)}/s +/-StdDev: {GetHumanReadableBytes(avgRps)}/s "); Console.WriteLine($"Connected : {devConn,10:N0} "); - Console.WriteLine($"CPU : {cpuPercent,10:N2}% Mem: {GetHumanReadableBytes(memoryBytes)} GC_Mem: {GetHumanReadableBytes(gcBytes)} TCP: {tcpConn,4:N0}"); + Console.WriteLine($"CPU Load : {(float)cpuLoad/100,10:N2} Mem: {GetHumanReadableBytes(memoryBytes)} GC_Mem: {GetHumanReadableBytes(gcBytes)} TCP: {tcpConn,4:N0}"); Console.WriteLine("----"); Console.WriteLine($"TOTALs: "); Console.WriteLine($"Requests : Completed: {statTotalCompleted,10:N0} Faulted: {statTotalFaulted,10:N0} Cancelled: {statTotalCancelled,10:N0}"); @@ -211,12 +211,12 @@ private async Task SetupAllAsync() double totalRequestsPerSec = statTotalCompleted / statTotalSeconds; (double avgRps, double stdDevRps) = CalculateAvgAndStDev(statRps); - SystemMetrics.GetMetrics(out int cpuPercent, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); + SystemMetrics.GetMetrics(out int cpuLoad, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); Console.WriteLine($"[{_sw.Elapsed}] Setup Statistics:"); Console.WriteLine($"RPS : {requestsPerSec,10:N2} R/s Avg: {avgRps,10:N2} R/s +/-StdDev: {stdDevRps,10:N2} R/s"); Console.WriteLine($"Connected : {devConn,10:N0} "); - Console.WriteLine($"CPU : {cpuPercent,10:N2}% Mem: {GetHumanReadableBytes(memoryBytes)} GC_Mem: {GetHumanReadableBytes(gcBytes)} TCP: {tcpConn,4:N0}"); + Console.WriteLine($"CPU Load : {(float)cpuLoad/100,10:N2} Mem: {GetHumanReadableBytes(memoryBytes)} GC_Mem: {GetHumanReadableBytes(gcBytes)} TCP: {tcpConn,4:N0}"); Console.WriteLine("----"); Console.WriteLine($"TOTALs: "); Console.WriteLine($"Requests : Completed: {statTotalCompleted,10:N0} Faulted: {statTotalFaulted,10:N0} Cancelled: {statTotalCancelled,10:N0}"); @@ -257,13 +257,13 @@ private async Task TeardownAllAsync() double totalRequestsPerSec = statTotalCompleted / statTotalSeconds; (double avgRps, double stdDevRps) = CalculateAvgAndStDev(statRps); - SystemMetrics.GetMetrics(out int cpuPercent, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); + SystemMetrics.GetMetrics(out int cpuLoad, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); Console.WriteLine($"[{_sw.Elapsed}] Teardown Statistics:"); Console.WriteLine($"RPS : {requestsPerSec,10:N2} R/s Avg: {avgRps,10:N2} R/s +/-StdDev: {stdDevRps,10:N2} R/s"); Console.WriteLine($"Connected : {devConn,10:N0} "); - Console.WriteLine($"CPU : {cpuPercent,10:N2}% Mem: {GetHumanReadableBytes(memoryBytes)} GC_Mem: {GetHumanReadableBytes(gcBytes)} TCP: {tcpConn,4:N0}"); + Console.WriteLine($"CPU Load : {(float)cpuLoad/100,10:N2} Mem: {GetHumanReadableBytes(memoryBytes)} GC_Mem: {GetHumanReadableBytes(gcBytes)} TCP: {tcpConn,4:N0}"); Console.WriteLine("----"); Console.WriteLine($"TOTALs: "); Console.WriteLine($"Requests : Completed: {statTotalCompleted,10:N0} Faulted: {statTotalFaulted,10:N0} Cancelled: {statTotalCancelled,10:N0}"); diff --git a/e2e/stress/IoTClientPerf/Properties/launchSettings.json b/e2e/stress/IoTClientPerf/Properties/launchSettings.json index 56d71f712c..96a7702b47 100644 --- a/e2e/stress/IoTClientPerf/Properties/launchSettings.json +++ b/e2e/stress/IoTClientPerf/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "IoTClientPerf": { "commandName": "Project", - "commandLineArgs": "-o s:\\tmp\\device.csv -t 60 -n 10 -f device_d2c" + "commandLineArgs": "-o device.csv -t 60 -n 10 -f device_d2c" } } } \ No newline at end of file diff --git a/e2e/stress/IoTClientPerf/Reporting/ResultWriter.cs b/e2e/stress/IoTClientPerf/Reporting/ResultWriter.cs index dfce46db5f..a2a52fbe70 100644 --- a/e2e/stress/IoTClientPerf/Reporting/ResultWriter.cs +++ b/e2e/stress/IoTClientPerf/Reporting/ResultWriter.cs @@ -8,12 +8,15 @@ namespace Microsoft.Azure.Devices.E2ETests public abstract class ResultWriter { protected string _header; + private const string NullInstance = "(null)"; public ResultWriter(string header = null) { _header = header; } + public static string IdOf(object value) => value != null ? value.GetType().Name + "#" + GetHashCode(value) : NullInstance; + public Task WriteAsync(TelemetryMetrics m) { return WriteLineAsync(m.ToString()); @@ -22,5 +25,7 @@ public Task WriteAsync(TelemetryMetrics m) public abstract Task FlushAsync(); protected abstract Task WriteLineAsync(string s); + + private static int GetHashCode(object value) => value?.GetHashCode() ?? 0; } } diff --git a/e2e/stress/IoTClientPerf/Reporting/ResultWriterFile.cs b/e2e/stress/IoTClientPerf/Reporting/ResultWriterFile.cs index 9b09d5e0eb..46e6d545c4 100644 --- a/e2e/stress/IoTClientPerf/Reporting/ResultWriterFile.cs +++ b/e2e/stress/IoTClientPerf/Reporting/ResultWriterFile.cs @@ -11,7 +11,7 @@ namespace Microsoft.Azure.Devices.E2ETests { public class ResultWriterFile : ResultWriter { - private const long MaximumFileSize = (long)2 * 1024 * 1024 * 1024; + private const long MaximumFileSize = (long)1 * 1024 * 1024 * 1024; private const int FileBufferBytes = 100 * 1024 * 1024; private StreamWriter _writer; private SemaphoreSlim _semaphore = new SemaphoreSlim(1); diff --git a/e2e/stress/IoTClientPerf/Reporting/SystemMetrics.cs b/e2e/stress/IoTClientPerf/Reporting/SystemMetrics.cs index f3ea358bd0..3e97ed2167 100644 --- a/e2e/stress/IoTClientPerf/Reporting/SystemMetrics.cs +++ b/e2e/stress/IoTClientPerf/Reporting/SystemMetrics.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.Net.NetworkInformation; using System.Text; @@ -12,10 +13,10 @@ namespace Microsoft.Azure.Devices.E2ETests { public static class SystemMetrics { - private const int RefreshIntervalMs = 1000; - private static readonly Stopwatch _sw = new Stopwatch(); - private static double s_lastTotalCpuUsageMs = 0.0; - private static int s_cpuPercent; + private const int RefreshIntervalMs = 500; + private static readonly Stopwatch s_sw = new Stopwatch(); + private static TimeSpan s_lastProcCpuUsageMs = TimeSpan.Zero; + private static int s_cpuLoad; private static long s_totalMemoryBytes; private static long s_lastGcBytes; private static long s_lastTcpConnections; @@ -23,12 +24,12 @@ public static class SystemMetrics private static long s_devicesConnected; - private static object s_lock = new object(); + private static readonly object s_lock = new object(); - public static void GetMetrics(out int cpuPercent, out long memoryBytes, out long gcBytes, out long tcpConn, out long devicesConn) + public static void GetMetrics(out int cpuLoad, out long memoryBytes, out long gcBytes, out long tcpConn, out long devicesConn) { EnsureUpToDate(); - cpuPercent = s_cpuPercent; + cpuLoad = s_cpuLoad; memoryBytes = s_totalMemoryBytes; gcBytes = s_lastGcBytes; tcpConn = s_lastTcpConnections; @@ -52,15 +53,23 @@ public static void TcpFilterPort(int port) private static void UpdateCpuUsage() { - var proc = Process.GetCurrentProcess(); - double currentTotalCpuUsageMs = proc.TotalProcessorTime.TotalMilliseconds / Environment.ProcessorCount; - double timeDeltaMs = _sw.Elapsed.TotalMilliseconds; + TimeSpan elapsed = s_sw.Elapsed; + Process proc = Process.GetCurrentProcess(); + + if ((elapsed.Ticks != 0) && (s_lastProcCpuUsageMs != TimeSpan.Zero)) + { - double usedTimeDeltaMs = currentTotalCpuUsageMs - s_lastTotalCpuUsageMs; - if (timeDeltaMs > 0.1) s_cpuPercent = (int)(usedTimeDeltaMs * 100 / timeDeltaMs); - if (s_cpuPercent > 100) s_cpuPercent = 100; + TimeSpan currentTotalCpuUsageMs = proc.TotalProcessorTime; + TimeSpan usedTimeDelta = currentTotalCpuUsageMs - s_lastProcCpuUsageMs; - s_lastTotalCpuUsageMs = currentTotalCpuUsageMs; + s_cpuLoad = (int)(((double)usedTimeDelta.Ticks / elapsed.Ticks) * 100); + } + else + { + s_cpuLoad = -1; + } + + s_lastProcCpuUsageMs = proc.TotalProcessorTime; } private static void UpdateTotalMemoryBytes() @@ -91,16 +100,20 @@ private static void UpdateTCPConnections() private static void EnsureUpToDate() { - if (!_sw.IsRunning || _sw.ElapsedMilliseconds > RefreshIntervalMs) + if (!s_sw.IsRunning) + { + s_sw.Start(); + } + else if (s_sw.ElapsedMilliseconds > RefreshIntervalMs) { lock (s_lock) { - UpdateCpuUsage(); UpdateGCMemoryBytes(); UpdateTCPConnections(); UpdateTotalMemoryBytes(); + UpdateCpuUsage(); - _sw.Restart(); + s_sw.Restart(); } } } diff --git a/e2e/stress/IoTClientPerf/Reporting/TelemetryMetrics.cs b/e2e/stress/IoTClientPerf/Reporting/TelemetryMetrics.cs index 2397de6701..dc35706437 100644 --- a/e2e/stress/IoTClientPerf/Reporting/TelemetryMetrics.cs +++ b/e2e/stress/IoTClientPerf/Reporting/TelemetryMetrics.cs @@ -12,6 +12,7 @@ public class TelemetryMetrics public const string DeviceOperationCreate = "device_create"; public const string DeviceOperationOpen = "device_open"; public const string DeviceOperationClose = "device_close"; + public const string DeviceOperationDispose = "device_dispose"; public const string DeviceOperationSend = "device_send"; public const string DeviceOperationReceive = "device_receive"; public const string DeviceOperationMethodEnable = "device_method_enable"; @@ -30,7 +31,7 @@ public class TelemetryMetrics private static string s_configString; // Contains all Config* parameters. public int? Id; - public string OperationType; // e.g. OpenAsync / SendAsync, etc + private string OperationType; // e.g. OpenAsync / SendAsync, etc public double? ScheduleTime; public double? ExecuteTime; public string ErrorMessage; @@ -62,6 +63,14 @@ public static string GetHeader() "ErrorMessage"; } + public void Clear(string operationType) + { + OperationType = operationType; + ScheduleTime = null; + ExecuteTime = null; + ErrorMessage = null; + } + public static void SetStaticConfigParameters( string runId, int timeSeconds, @@ -87,9 +96,9 @@ public override string ToString() Add(sb, ScheduleTime); Add(sb, ExecuteTime); - SystemMetrics.GetMetrics(out int cpuPercent, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); + SystemMetrics.GetMetrics(out int cpuLoad, out long memoryBytes, out long gcBytes, out long tcpConn, out long devConn); - Add(sb, cpuPercent); + Add(sb, cpuLoad); Add(sb, memoryBytes); Add(sb, gcBytes); Add(sb, tcpConn); diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceAllNoRetry.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceAllNoRetry.cs index 3bb06b2e0b..c062df15dd 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceAllNoRetry.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/DeviceAllNoRetry.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using Microsoft.Azure.Devices.Client.Exceptions; +using System; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; @@ -8,6 +11,8 @@ namespace Microsoft.Azure.Devices.E2ETests { public class DeviceAllNoRetry : DeviceClientScenario { + private const int DelaySecondsAfterFailure = 1; + private readonly SemaphoreSlim _lock = new SemaphoreSlim(1); private Task _sendTask; private Task _receiveTask; private Task _waitForMethodTask; @@ -28,14 +33,37 @@ public override async Task SetupAsync(CancellationToken ct) public override async Task RunTestAsync(CancellationToken ct) { - SetupTasks(ct); - Task completedTask = await Task.WhenAny(_waitForDisconnectTask, _sendTask, _receiveTask, _waitForMethodTask).ConfigureAwait(false); - - if (completedTask == _waitForDisconnectTask) + try { - DisposeDevice(); - await SetupAsync(ct).ConfigureAwait(false); + await _lock.WaitAsync().ConfigureAwait(false); SetupTasks(ct); + + Task completedTask = await Task.WhenAny(_waitForDisconnectTask, _sendTask, _receiveTask, _waitForMethodTask).ConfigureAwait(false); + + if (completedTask == _waitForDisconnectTask) + { + await DisposeDevice().ConfigureAwait(false); + + try + { + // Drain current operations. Method will not be notified in any way of the disconnect. + await Task.WhenAll(_sendTask, _receiveTask).ConfigureAwait(false); + } + catch (IotHubException) { } + catch (OperationCanceledException) { } + + _waitForDisconnectTask = null; + _sendTask = null; + _receiveTask = null; + _waitForMethodTask = null; + + await Task.Delay(DelaySecondsAfterFailure * 1000).ConfigureAwait(false); + await SetupAsync(ct).ConfigureAwait(false); + } + } + finally + { + _lock.Release(); } } diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs index 8fac2e3b14..4affde7b24 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs @@ -30,7 +30,7 @@ public override async Task RunTestAsync(CancellationToken ct) if (completedTask == _waitForDisconnectTask) { - DisposeDevice(); + await DisposeDevice().ConfigureAwait(false); await SetupAsync(ct).ConfigureAwait(false); SetupTasks(ct); } diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceClientScenario.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceClientScenario.cs index 4e5b136ea6..a2c6fc73e4 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceClientScenario.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/DeviceClientScenario.cs @@ -17,41 +17,35 @@ public abstract class DeviceClientScenario : PerfScenario private DeviceClient _dc; // Shared by Create, Open and Send - private TelemetryMetrics _m = new TelemetryMetrics(); - private Stopwatch _sw = new Stopwatch(); + private readonly TelemetryMetrics _m = new TelemetryMetrics(); + private readonly Stopwatch _sw = new Stopwatch(); // Separate metrics and time calculation for operations that can be parallelized. - private TelemetryMetrics _mRecv = new TelemetryMetrics(); - private Stopwatch _swRecv = new Stopwatch(); + private readonly TelemetryMetrics _mRecv = new TelemetryMetrics(); + private readonly Stopwatch _swRecv = new Stopwatch(); - private const string TestMethodName = "PerfTestMethod"; - private TelemetryMetrics _mMethod = new TelemetryMetrics(); - private Stopwatch _swMethod = new Stopwatch(); - private SemaphoreSlim _methodSemaphore = new SemaphoreSlim(0); + private const string TestMethodName = "SendMessageToDevice"; + private readonly TelemetryMetrics _mMethod = new TelemetryMetrics(); + private readonly Stopwatch _swMethod = new Stopwatch(); + private readonly SemaphoreSlim _methodSemaphore = new SemaphoreSlim(0); private static readonly MethodResponse s_methodResponse = new MethodResponse(200); - private TelemetryMetrics _mConnectionStatus = new TelemetryMetrics(); - private SemaphoreSlim _connectionStatusChangedSemaphore = new SemaphoreSlim(0); - private SemaphoreSlim _waitForDisconnectSemaphore = new SemaphoreSlim(0); + private readonly TelemetryMetrics _mConnectionStatus = new TelemetryMetrics(); + private readonly SemaphoreSlim _connectionStatusChangedSemaphore = new SemaphoreSlim(1); + private readonly SemaphoreSlim _waitForDisconnectSemaphore = new SemaphoreSlim(0, 1); private bool _connected; - private byte[] _messageBytes; + private readonly byte[] _messageBytes; - private bool _pooled; - private int _poolSize; + private readonly bool _pooled; + private readonly int _poolSize; public DeviceClientScenario(PerfScenarioConfig config) : base(config) { _m.Id = _id; - _mRecv.Id = _id; - _mRecv.OperationType = TelemetryMetrics.DeviceOperationReceive; - _mMethod.Id = _id; - _mConnectionStatus.Id = _id; - _mConnectionStatus.ExecuteTime = null; - _mConnectionStatus.ScheduleTime = null; _messageBytes = new byte[_sizeBytes]; @@ -64,7 +58,7 @@ public DeviceClientScenario(PerfScenarioConfig config) : base(config) protected async Task CreateDeviceAsync() { _sw.Restart(); - _m.OperationType = TelemetryMetrics.DeviceOperationCreate; + _m.Clear(TelemetryMetrics.DeviceOperationCreate); ITransportSettings transportSettings = null; @@ -108,7 +102,6 @@ protected async Task CreateDeviceAsync() _dc.SetConnectionStatusChangesHandler(OnConnectionStatusChanged); _m.ExecuteTime = _sw.ElapsedMilliseconds; - _m.ScheduleTime = null; // sync operation await _writer.WriteAsync(_m).ConfigureAwait(false); } @@ -132,8 +125,13 @@ private async void OnConnectionStatusChanged(ConnectionStatus status, Connection _connected = false; } - _mConnectionStatus.OperationType = TelemetryMetrics.DeviceStateDisconnected; - _waitForDisconnectSemaphore.Release(); + _mConnectionStatus.Clear(TelemetryMetrics.DeviceStateDisconnected); + try + { + _waitForDisconnectSemaphore.Release(); + } + catch (SemaphoreFullException) { } + break; case ConnectionStatus.Connected: if (!_connected) @@ -142,7 +140,7 @@ private async void OnConnectionStatusChanged(ConnectionStatus status, Connection _connected = true; } - _mConnectionStatus.OperationType = TelemetryMetrics.DeviceStateConnected; + _mConnectionStatus.Clear(TelemetryMetrics.DeviceStateConnected); break; case ConnectionStatus.Disconnected_Retrying: if (_connected) @@ -151,8 +149,14 @@ private async void OnConnectionStatusChanged(ConnectionStatus status, Connection _connected = false; } - _mConnectionStatus.OperationType = TelemetryMetrics.DeviceStateDisconnectedRetrying; - _waitForDisconnectSemaphore.Release(); + _mConnectionStatus.Clear(TelemetryMetrics.DeviceStateDisconnectedRetrying); + + try + { + _waitForDisconnectSemaphore.Release(); + } + catch (SemaphoreFullException) { } + break; case ConnectionStatus.Disabled: if (_connected) @@ -161,14 +165,14 @@ private async void OnConnectionStatusChanged(ConnectionStatus status, Connection _connected = false; } - _mConnectionStatus.OperationType = TelemetryMetrics.DeviceStateDisconnected; + _mConnectionStatus.Clear(TelemetryMetrics.DeviceStateDisconnected); break; default: - _mConnectionStatus.OperationType = TelemetryMetrics.DeviceStateUnknown; + _mConnectionStatus.Clear(TelemetryMetrics.DeviceStateUnknown); break; } - _mConnectionStatus.ErrorMessage = $"ConnectionStatus: {status} reason: {reason}"; + _mConnectionStatus.ErrorMessage = $"ConnectionStatus: {status} reason: {reason} id: {ResultWriter.IdOf(_dc)}"; await _writer.WriteAsync(_mConnectionStatus).ConfigureAwait(false); } finally @@ -184,8 +188,8 @@ protected Task WaitForDisconnectedAsync(CancellationToken ct) protected async Task OpenDeviceAsync(CancellationToken ct) { - _m.OperationType = TelemetryMetrics.DeviceOperationOpen; - _m.ScheduleTime = null; + _m.Clear(TelemetryMetrics.DeviceOperationOpen); + _sw.Restart(); try { @@ -197,7 +201,7 @@ protected async Task OpenDeviceAsync(CancellationToken ct) } catch (Exception ex) { - _m.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + SetErrorMessage(_m, ex); throw; } finally @@ -209,8 +213,8 @@ protected async Task OpenDeviceAsync(CancellationToken ct) protected async Task SendMessageAsync(CancellationToken ct) { - _m.OperationType = TelemetryMetrics.DeviceOperationSend; - _m.ScheduleTime = null; + _m.Clear(TelemetryMetrics.DeviceOperationSend); + _sw.Restart(); try @@ -224,7 +228,7 @@ protected async Task SendMessageAsync(CancellationToken ct) } catch (Exception ex) { - _m.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + SetErrorMessage(_m, ex); throw; } finally @@ -236,7 +240,7 @@ protected async Task SendMessageAsync(CancellationToken ct) protected async Task ReceiveMessageAsync(CancellationToken ct) { - _mRecv.ScheduleTime = null; + _mRecv.Clear(TelemetryMetrics.DeviceOperationReceive); _swRecv.Restart(); try @@ -253,7 +257,7 @@ protected async Task ReceiveMessageAsync(CancellationToken ct) } catch (Exception ex) { - _mRecv.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + SetErrorMessage(_mRecv, ex); throw; } finally @@ -265,8 +269,7 @@ protected async Task ReceiveMessageAsync(CancellationToken ct) protected async Task EnableMethodsAsync(CancellationToken ct) { - _mMethod.ScheduleTime = null; - _mMethod.OperationType = TelemetryMetrics.DeviceOperationMethodEnable; + _mMethod.Clear(TelemetryMetrics.DeviceOperationMethodEnable); _swMethod.Restart(); try @@ -279,7 +282,7 @@ protected async Task EnableMethodsAsync(CancellationToken ct) } catch (Exception ex) { - _mMethod.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + SetErrorMessage(_mMethod, ex); throw; } finally @@ -297,8 +300,7 @@ private Task MethodHandlerAsync(MethodRequest methodRequest, obj protected async Task WaitForMethodAsync(CancellationToken ct) { - _mMethod.ScheduleTime = null; - _mMethod.OperationType = TelemetryMetrics.DeviceOperationMethodCalled; + _mMethod.Clear(TelemetryMetrics.DeviceOperationMethodCalled); _swMethod.Restart(); try @@ -311,7 +313,7 @@ protected async Task WaitForMethodAsync(CancellationToken ct) } catch (Exception ex) { - _mMethod.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + SetErrorMessage(_mMethod, ex); throw; } finally @@ -325,8 +327,7 @@ protected async Task CloseAsync(CancellationToken ct) { if (_dc == null) return; - _m.ScheduleTime = null; - _m.OperationType = TelemetryMetrics.DeviceOperationClose; + _m.Clear(TelemetryMetrics.DeviceOperationClose); _sw.Restart(); try @@ -335,7 +336,7 @@ protected async Task CloseAsync(CancellationToken ct) } catch (Exception ex) { - _m.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + SetErrorMessage(_m, ex); throw; } finally @@ -345,9 +346,16 @@ protected async Task CloseAsync(CancellationToken ct) } } - protected void DisposeDevice() + private void SetErrorMessage(TelemetryMetrics m, Exception ex) { + m.ErrorMessage = $"{ex.GetType().Name} id: {ResultWriter.IdOf(_dc)} - {ex.Message}"; + } + + protected async Task DisposeDevice() + { + _m.Clear(TelemetryMetrics.DeviceOperationDispose); _dc.Dispose(); + await _writer.WriteAsync(_m).ConfigureAwait(false); } } } diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs index 258b900113..2a36bc79be 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs @@ -30,7 +30,7 @@ public override async Task RunTestAsync(CancellationToken ct) if (completedTask == _waitForDisconnectTask) { - DisposeDevice(); + await DisposeDevice().ConfigureAwait(false); await SetupAsync(ct).ConfigureAwait(false); SetupTasks(ct); } diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs index 56ae25dbd8..a19399b9e0 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs @@ -30,7 +30,7 @@ public override async Task RunTestAsync(CancellationToken ct) if (completedTask == _waitForDisconnectTask) { - DisposeDevice(); + await DisposeDevice().ConfigureAwait(false); await SetupAsync(ct).ConfigureAwait(false); SetupTasks(ct); } diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceOneD2CTest.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceOneD2CTest.cs index 030f039993..ab5ff708cf 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceOneD2CTest.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/DeviceOneD2CTest.cs @@ -42,7 +42,7 @@ public override async Task SetupAsync(CancellationToken ct) private async Task CreateDeviceAsync() { _sw.Restart(); - _m.OperationType = TelemetryMetrics.DeviceOperationCreate; + _m.Clear(TelemetryMetrics.DeviceOperationCreate); ITransportSettings transportSettings = null; @@ -79,8 +79,7 @@ private async Task CreateDeviceAsync() protected async Task OpenDeviceAsync(CancellationToken ct) { ExceptionDispatchInfo exInfo = null; - _m.OperationType = TelemetryMetrics.DeviceOperationOpen; - _m.ScheduleTime = null; + _m.Clear(TelemetryMetrics.DeviceOperationOpen); _sw.Restart(); try { @@ -110,8 +109,7 @@ public override Task RunTestAsync(CancellationToken ct) protected async Task SendMessageAsync(CancellationToken ct) { ExceptionDispatchInfo exInfo = null; - _m.OperationType = TelemetryMetrics.DeviceOperationSend; - _m.ScheduleTime = null; + _m.Clear(TelemetryMetrics.DeviceOperationSend); _sw.Restart(); try diff --git a/e2e/stress/IoTClientPerf/Scenarios/HarnessBaseline.cs b/e2e/stress/IoTClientPerf/Scenarios/HarnessBaseline.cs index 4fbf7ccf8c..d387028dcc 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/HarnessBaseline.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/HarnessBaseline.cs @@ -24,7 +24,7 @@ public HarnessBaseline(PerfScenarioConfig config) : base(config) public override async Task SetupAsync(CancellationToken ct) { _sw.Restart(); - _m.OperationType = "baseline_setup"; + _m.Clear("baseline_setup"); await Task.Delay(100).ConfigureAwait(false); _m.ExecuteTime = _sw.ElapsedMilliseconds; _m.ScheduleTime = null; // sync operation @@ -34,7 +34,7 @@ public override async Task SetupAsync(CancellationToken ct) public override async Task RunTestAsync(CancellationToken ct) { _sw.Restart(); - _m.OperationType = "baseline_run"; + _m.Clear("baseline_run"); await Task.Delay(100).ConfigureAwait(false); _m.ExecuteTime = _sw.ElapsedMilliseconds; _m.ScheduleTime = null; // sync operation @@ -44,7 +44,7 @@ public override async Task RunTestAsync(CancellationToken ct) public override async Task TeardownAsync(CancellationToken ct) { _sw.Restart(); - _m.OperationType = "baseline_teardown"; + _m.Clear("baseline_teardown"); await Task.Delay(100).ConfigureAwait(false); _m.ExecuteTime = _sw.ElapsedMilliseconds; _m.ScheduleTime = null; // sync operation diff --git a/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs b/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs index ef1d586d32..941ad28244 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs @@ -3,7 +3,7 @@ using System; using System.Diagnostics; -using System.Runtime.ExceptionServices; +using System.Globalization; using System.Threading; using System.Threading.Tasks; @@ -42,13 +42,32 @@ public ServiceClientScenario(PerfScenarioConfig config) : base(config) protected void CreateServiceClient() { - if (_id == 0) s_sc = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); + if (_id != 0) return; + s_sc?.Dispose(); + + switch (_transport) + { + case Client.TransportType.Amqp_WebSocket_Only: + s_sc = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString, TransportType.Amqp_WebSocket_Only); + break; + case Client.TransportType.Amqp_Tcp_Only: + s_sc = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString, TransportType.Amqp); + break; + + case Client.TransportType.Amqp: + case Client.TransportType.Http1: + case Client.TransportType.Mqtt: + case Client.TransportType.Mqtt_WebSocket_Only: + case Client.TransportType.Mqtt_Tcp_Only: + default: + s_sc = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); + break; + } } protected async Task OpenServiceClientAsync(CancellationToken ct) { - _m.OperationType = TelemetryMetrics.ServiceOperationOpen; - _m.ScheduleTime = null; + _m.Clear(TelemetryMetrics.ServiceOperationOpen); _sw.Restart(); try { @@ -58,6 +77,12 @@ protected async Task OpenServiceClientAsync(CancellationToken ct) _sw.Restart(); await t.ConfigureAwait(false); } + catch (NullReferenceException ex) // TODO #708 - ServiceClient AMQP will continuously fail with NullRefException after fault. + { + CreateServiceClient(); + _m.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + throw; + } catch (Exception ex) { _m.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; @@ -72,19 +97,25 @@ protected async Task OpenServiceClientAsync(CancellationToken ct) protected async Task SendMessageAsync(CancellationToken ct) { - _m.OperationType = TelemetryMetrics.ServiceOperationSend; - _m.ScheduleTime = null; + _m.Clear(TelemetryMetrics.ServiceOperationSend); _sw.Restart(); try { var message = new Message(_messageBytes); + message.ExpiryTimeUtc = DateTime.UtcNow + TimeSpan.FromSeconds(90); Task t = s_sc.SendAsync(Configuration.Stress.GetDeviceNameById(_id, _authType), message); _m.ScheduleTime = _sw.ElapsedMilliseconds; _sw.Restart(); await t.ConfigureAwait(false); } + catch (NullReferenceException ex) // TODO #708 - ServiceClient AMQP will continuously fail with NullRefException after fault. + { + CreateServiceClient(); + _m.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; + throw; + } catch (Exception ex) { _m.ErrorMessage = $"{ex.GetType().Name} - {ex.Message}"; @@ -99,15 +130,14 @@ protected async Task SendMessageAsync(CancellationToken ct) protected async Task CallMethodAsync(CancellationToken ct) { - _mMethod.ScheduleTime = null; - _mMethod.OperationType = TelemetryMetrics.ServiceOperationMethodCall; + _mMethod.Clear(TelemetryMetrics.ServiceOperationMethodCall); _swMethod.Restart(); try { string deviceId = Configuration.Stress.GetDeviceNameById(_id, _authType); - var methodCall = new CloudToDeviceMethod(TestMethodName); + var methodCall = new CloudToDeviceMethod(methodName: TestMethodName, responseTimeout: TimeSpan.FromSeconds(30), connectionTimeout: TimeSpan.FromSeconds(30)); methodCall.SetPayloadJson(_methodPayload); Task t = s_sc.InvokeDeviceMethodAsync(Configuration.Stress.GetDeviceNameById(_id, _authType), methodCall); _mMethod.ScheduleTime = _swMethod.ElapsedMilliseconds; @@ -137,8 +167,7 @@ protected async Task CloseAsync(CancellationToken ct) { if (s_sc == null) return; - _m.ScheduleTime = null; - _m.OperationType = TelemetryMetrics.ServiceOperationClose; + _m.Clear(TelemetryMetrics.ServiceOperationClose); _sw.Restart(); try diff --git a/e2e/stress/IoTClientPerf/scripts/runClient.ps1 b/e2e/stress/IoTClientPerf/scripts/runClient.ps1 index 7370801637..b31fd4dc93 100644 --- a/e2e/stress/IoTClientPerf/scripts/runClient.ps1 +++ b/e2e/stress/IoTClientPerf/scripts/runClient.ps1 @@ -24,18 +24,31 @@ Param( $host.ui.RawUI.WindowTitle = "Azure IoT SDK: Device Stress" +$fileName = [io.path]::GetFileNameWithoutExtension($outputFile) +$filePath = [io.path]::GetDirectoryName($outputFile) +if ($filePath -eq "") { + $filePath = pwd +} Write-Host -ForegroundColor Cyan "`nDEVICE: C2D`n" -& dotnet run --no-build -c Release -- -t $durationSeconds -o $outputFile -p $protocol -n $clients -c $connections -f device_c2d +$scenario = "device_c2d" +$out = Join-Path $filePath "$fileName.$($scenario).csv" +& dotnet run --no-build -c Release -- -t $durationSeconds -o $out -p $protocol -n $clients -c $connections -f $scenario -s 2048 Write-Host -ForegroundColor Cyan "`nDEVICE: Methods`n" -& dotnet run --no-build -c Release -- -t $durationSeconds -o $outputFile -p $protocol -n $clients -c $connections -f device_method - +$scenario = "device_method" +$out = Join-Path $filePath "$fileName.$($scenario).csv" +& dotnet run --no-build -c Release -- -t $durationSeconds -o $out -p $protocol -n $clients -c $connections -f $scenario -s 2048 Write-Host -ForegroundColor Cyan "`nDEVICE: All`n" -& dotnet run --no-build -c Release -- -t $durationSeconds -o $outputFile -p $protocol -n $clients -c $connections -f device_all +$scenario = "device_all" +$out = Join-Path $filePath "$fileName.$($scenario).csv" + +& dotnet run --no-build -c Release -- -t $durationSeconds -o $out -p $protocol -n $clients -c $connections -f $scenario -s 2048 Write-Host -ForegroundColor Cyan "`nDEVICE: D2C`n" -& dotnet run --no-build -c Release -- -t $durationSeconds -o $outputFile -p $protocol -n $clients -c $connections -f device_d2c +$scenario = "device_d2c" +$out = Join-Path $filePath "$fileName.$($scenario).csv" +& dotnet run --no-build -c Release -- -t $durationSeconds -o $out -p $protocol -n $clients -c $connections -f $scenario -s 2048 diff --git a/e2e/stress/IoTClientPerf/scripts/runServer.ps1 b/e2e/stress/IoTClientPerf/scripts/runServer.ps1 index 39a5ba28b2..e38eb0edfd 100644 --- a/e2e/stress/IoTClientPerf/scripts/runServer.ps1 +++ b/e2e/stress/IoTClientPerf/scripts/runServer.ps1 @@ -19,13 +19,16 @@ Param( $protocol = "amqp", $connections = 10, $outputFile = "service.csv", - $durationSeconds = 1800, + $durationSeconds = 300, $type = $null ) $fileName = [io.path]::GetFileNameWithoutExtension($outputFile) $filePath = [io.path]::GetDirectoryName($outputFile) +if ($filePath -eq "") { + $filePath = pwd +} if ($type -eq $null) { @@ -44,15 +47,25 @@ elseif ($type -eq "methods") $host.ui.RawUI.WindowTitle = "Azure IoT SDK: Service Stress [Methods]" Write-Host -ForegroundColor Cyan "`nSERVICE: Methods`n" - $out = Join-Path $filePath "$fileName.method.csv" $scenario = "service_method" + $out = Join-Path $filePath "$fileName.$($scenario).csv" + if (Test-Path $out) + { + rm $out + } + } elseif ($type -eq "c2d") { $host.ui.RawUI.WindowTitle = "Azure IoT SDK: Service Stress [C2D]" Write-Host -ForegroundColor Cyan "`nSERVICE: C2D`n" - $out = Join-Path $filePath "$fileName.c2d.csv" $scenario = "service_c2d" + $out = Join-Path $filePath "$fileName.$($scenario).csv" + + if (Test-Path $out) + { + rm $out + } } else { @@ -60,5 +73,5 @@ else } -& dotnet run --no-build -c Release -- -t $durationSeconds -o $out -p $protocol -n $clients -c $connections -f $scenario +& dotnet run --no-build -c Release -- -t $durationSeconds -o $out -p $protocol -n $clients -c $connections -f $scenario -s 2048 Read-Host "Press ENTER to close" From 80546b110de75013b45c3ab5b1404a7afc160727 Mon Sep 17 00:00:00 2001 From: Cristian Pop Date: Tue, 17 Sep 2019 16:16:11 -0700 Subject: [PATCH 2/2] Extracting timeouts as constants. --- e2e/stress/IoTClientPerf/Program.cs | 17 ------- .../Scenarios/DeviceC2DNoRetry.cs | 50 ------------------- .../Scenarios/DeviceD2CNoRetry.cs | 50 ------------------- .../Scenarios/DeviceMethodsNoRetry.cs | 50 ------------------- .../Scenarios/ServiceClientScenarios.cs | 12 ++++- 5 files changed, 10 insertions(+), 169 deletions(-) delete mode 100644 e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs delete mode 100644 e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs delete mode 100644 e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs diff --git a/e2e/stress/IoTClientPerf/Program.cs b/e2e/stress/IoTClientPerf/Program.cs index 7a570610d2..3116611da9 100644 --- a/e2e/stress/IoTClientPerf/Program.cs +++ b/e2e/stress/IoTClientPerf/Program.cs @@ -3,9 +3,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; -using System.Net.NetworkInformation; namespace Microsoft.Azure.Devices.E2ETests { @@ -49,21 +47,6 @@ private static Dictionary {return new DeviceMethodTest(c);}) }, - { "device_d2c_noretry", - new Tuple>( - "Like device_d2c but will disable retries and create a new DeviceClient when the previous enters a faulted state.", - (c) => {return new DeviceD2CNoRetry(c);})}, - - { "device_c2d_noretry", - new Tuple>( - "Like device_c2d but will disable retries and create a new DeviceClient when the previous enters a faulted state.", - (c) => {return new DeviceC2DNoRetry(c);})}, - - { "device_methods_noretry", - new Tuple>( - "Like device_methods but will disable retries and create a new DeviceClient when the previous enters a faulted state.", - (c) => {return new DeviceMethodsNoRetry(c);})}, - {"service_c2d", new Tuple>( "ServiceClient sending events to devices through IoT Hub.", diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs deleted file mode 100644 index 4affde7b24..0000000000 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceC2DNoRetry.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Azure.Devices.E2ETests -{ - public class DeviceC2DNoRetry : DeviceClientScenario - { - private Task _receiveTask; - private Task _waitForDisconnectTask; - - - public DeviceC2DNoRetry(PerfScenarioConfig config) : base(config) - { - } - - public override async Task SetupAsync(CancellationToken ct) - { - await CreateDeviceAsync().ConfigureAwait(false); - DisableRetry(); - await OpenDeviceAsync(ct).ConfigureAwait(false); - } - - public override async Task RunTestAsync(CancellationToken ct) - { - SetupTasks(ct); - Task completedTask = await Task.WhenAny(_waitForDisconnectTask, _receiveTask).ConfigureAwait(false); - - if (completedTask == _waitForDisconnectTask) - { - await DisposeDevice().ConfigureAwait(false); - await SetupAsync(ct).ConfigureAwait(false); - SetupTasks(ct); - } - } - - private void SetupTasks(CancellationToken ct) - { - if (_waitForDisconnectTask == null || _waitForDisconnectTask.IsCompleted) _waitForDisconnectTask = WaitForDisconnectedAsync(ct); - if (_receiveTask == null || _receiveTask.IsCompleted) _receiveTask = ReceiveMessageAsync(ct); - } - - public override Task TeardownAsync(CancellationToken ct) - { - return CloseAsync(ct); - } - } -} diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs deleted file mode 100644 index 2a36bc79be..0000000000 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceD2CNoRetry.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Azure.Devices.E2ETests -{ - public class DeviceD2CNoRetry : DeviceClientScenario - { - private Task _sendTask; - private Task _waitForDisconnectTask; - - - public DeviceD2CNoRetry(PerfScenarioConfig config) : base(config) - { - } - - public override async Task SetupAsync(CancellationToken ct) - { - await CreateDeviceAsync().ConfigureAwait(false); - DisableRetry(); - await OpenDeviceAsync(ct).ConfigureAwait(false); - } - - public override async Task RunTestAsync(CancellationToken ct) - { - SetupTasks(ct); - Task completedTask = await Task.WhenAny(_waitForDisconnectTask, _sendTask).ConfigureAwait(false); - - if (completedTask == _waitForDisconnectTask) - { - await DisposeDevice().ConfigureAwait(false); - await SetupAsync(ct).ConfigureAwait(false); - SetupTasks(ct); - } - } - - private void SetupTasks(CancellationToken ct) - { - if (_waitForDisconnectTask == null || _waitForDisconnectTask.IsCompleted) _waitForDisconnectTask = WaitForDisconnectedAsync(ct); - if (_sendTask == null || _sendTask.IsCompleted) _sendTask = SendMessageAsync(ct); - } - - public override Task TeardownAsync(CancellationToken ct) - { - return CloseAsync(ct); - } - } -} diff --git a/e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs b/e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs deleted file mode 100644 index a19399b9e0..0000000000 --- a/e2e/stress/IoTClientPerf/Scenarios/DeviceMethodsNoRetry.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Azure.Devices.E2ETests -{ - public class DeviceMethodsNoRetry : DeviceClientScenario - { - private Task _waitForMethodTask; - private Task _waitForDisconnectTask; - - public DeviceMethodsNoRetry(PerfScenarioConfig config) : base(config) - { - } - - public override async Task SetupAsync(CancellationToken ct) - { - await CreateDeviceAsync().ConfigureAwait(false); - DisableRetry(); - await OpenDeviceAsync(ct).ConfigureAwait(false); - await EnableMethodsAsync(ct).ConfigureAwait(false); - } - - public override async Task RunTestAsync(CancellationToken ct) - { - SetupTasks(ct); - Task completedTask = await Task.WhenAny(_waitForDisconnectTask, _waitForMethodTask).ConfigureAwait(false); - - if (completedTask == _waitForDisconnectTask) - { - await DisposeDevice().ConfigureAwait(false); - await SetupAsync(ct).ConfigureAwait(false); - SetupTasks(ct); - } - } - - private void SetupTasks(CancellationToken ct) - { - if (_waitForDisconnectTask == null || _waitForDisconnectTask.IsCompleted) _waitForDisconnectTask = WaitForDisconnectedAsync(ct); - if (_waitForMethodTask == null || _waitForMethodTask.IsCompleted) _waitForMethodTask = WaitForMethodAsync(ct); - } - - public override Task TeardownAsync(CancellationToken ct) - { - return CloseAsync(ct); - } - } -} diff --git a/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs b/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs index 941ad28244..443c6c303f 100644 --- a/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs +++ b/e2e/stress/IoTClientPerf/Scenarios/ServiceClientScenarios.cs @@ -20,6 +20,11 @@ public abstract class ServiceClientScenario : PerfScenario // Separate metrics and time calculation for operations that can be parallelized. private const string TestMethodName = "PerfTestMethod"; private const int MethodPassStatus = 200; + private const int MethodConnectionTimeoutSeconds = 30; + private const int MethodResponseTimeoutSeconds = 30; + + private const int C2DExpiryTimeSeconds = 90; + private TelemetryMetrics _mMethod = new TelemetryMetrics(); private Stopwatch _swMethod = new Stopwatch(); @@ -103,7 +108,7 @@ protected async Task SendMessageAsync(CancellationToken ct) try { var message = new Message(_messageBytes); - message.ExpiryTimeUtc = DateTime.UtcNow + TimeSpan.FromSeconds(90); + message.ExpiryTimeUtc = DateTime.UtcNow + TimeSpan.FromSeconds(C2DExpiryTimeSeconds); Task t = s_sc.SendAsync(Configuration.Stress.GetDeviceNameById(_id, _authType), message); _m.ScheduleTime = _sw.ElapsedMilliseconds; @@ -137,7 +142,10 @@ protected async Task CallMethodAsync(CancellationToken ct) { string deviceId = Configuration.Stress.GetDeviceNameById(_id, _authType); - var methodCall = new CloudToDeviceMethod(methodName: TestMethodName, responseTimeout: TimeSpan.FromSeconds(30), connectionTimeout: TimeSpan.FromSeconds(30)); + var methodCall = new CloudToDeviceMethod( + methodName: TestMethodName, + responseTimeout: TimeSpan.FromSeconds(MethodResponseTimeoutSeconds), + connectionTimeout: TimeSpan.FromSeconds(MethodConnectionTimeoutSeconds)); methodCall.SetPayloadJson(_methodPayload); Task t = s_sc.InvokeDeviceMethodAsync(Configuration.Stress.GetDeviceNameById(_id, _authType), methodCall); _mMethod.ScheduleTime = _swMethod.ElapsedMilliseconds;