Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HTTP/3] Revert msquic hack in stress tests #87926

Closed
Closed
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
3 changes: 0 additions & 3 deletions eng/docker/build-docker-sdk.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ if ($buildWindowsContainers)
# 2. Runtime pack (microsoft.netcore.app.runtime.win-x64)
# 3. targetingpacks.targets, so stress test builds can target the live-built runtime instead of the one in the pre-installed SDK
# 4. testhost
# 5. msquic interop sources (needed for HttpStress)
$binArtifacts = "$REPO_ROOT_DIR\artifacts\bin"
$dockerContext = "$REPO_ROOT_DIR\artifacts\docker-context"

Expand All @@ -52,8 +51,6 @@ if ($buildWindowsContainers)
-Destination $dockerContext\testhost
Copy-Item -Recurse -Path $REPO_ROOT_DIR\eng\targetingpacks.targets `
-Destination $dockerContext\targetingpacks.targets
Copy-Item -Recurse -Path $REPO_ROOT_DIR\src\libraries\System.Net.Quic\src\System\Net\Quic\Interop `
-Destination $dockerContext\msquic-interop

# In case of non-CI builds, testhost may already contain Microsoft.AspNetCore.App (see build-local.ps1 in HttpStress):
$testHostAspNetCorePath="$dockerContext\testhost\net$dotNetVersion-windows-$configuration-x64/shared/Microsoft.AspNetCore.App"
Expand Down
5 changes: 0 additions & 5 deletions eng/docker/libraries-sdk.linux.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ RUN bash ./dotnet-install.sh --channel $_DOTNET_INSTALL_CHANNEL --quality daily
# 2. Runtime pack (microsoft.netcore.app.runtime.linux-x64)
# 3. targetingpacks.targets, so stress test builds can target the live-built runtime instead of the one in the pre-installed SDK
# 4. testhost
# 5. msquic interop sources (needed for HttpStress)

COPY --from=corefxbuild \
/repo/artifacts/bin/microsoft.netcore.app.ref \
Expand All @@ -44,10 +43,6 @@ COPY --from=corefxbuild \
/repo/artifacts/bin/testhost \
/live-runtime-artifacts/testhost

COPY --from=corefxbuild \
/repo/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop \
/live-runtime-artifacts/msquic-interop

# Add AspNetCore bits to testhost:
ENV _ASPNETCORE_SOURCE="/usr/share/dotnet/shared/Microsoft.AspNetCore.App/$VERSION*"
ENV _ASPNETCORE_DEST="/live-runtime-artifacts/testhost/net$VERSION-linux-$CONFIGURATION-x64/shared/Microsoft.AspNetCore.App"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<!-- Stress projects have their own global.json, the directory above that also has it is the repository root. -->
<RepositoryRoot>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)../, global.json))/</RepositoryRoot>

<MsQuicInteropIncludes Condition="'$(MsQuicInteropIncludes)' == ''">$(RepositoryRoot)src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/*.cs</MsQuicInteropIncludes>
<TargetingPacksTargetsLocation Condition="'$(TargetingPacksTargetsLocation)' == ''">$(RepositoryRoot)eng/targetingpacks.targets</TargetingPacksTargetsLocation>
<ProductVersion>8.0.0</ProductVersion>
<NetCoreAppCurrent>net8.0</NetCoreAppCurrent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ WORKDIR /app
COPY . .

RUN dotnet build -c $CONFIGURATION \
-p:MsQuicInteropIncludes="/live-runtime-artifacts/msquic-interop/*.cs" \
-p:TargetingPacksTargetsLocation=/live-runtime-artifacts/targetingpacks.targets \
-p:MicrosoftNetCoreAppRefPackDir=/live-runtime-artifacts/microsoft.netcore.app.ref/ \
-p:MicrosoftNetCoreAppRuntimePackDir=/live-runtime-artifacts/microsoft.netcore.app.runtime.linux-x64/$CONFIGURATION/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@
<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.5.4" />
</ItemGroup>

<!-- Shared production code -->
<ItemGroup>
<Compile Include="$(MsQuicInteropIncludes)" LinkBase="MsQuicInterop" />
</ItemGroup>

<PropertyGroup>
<!-- These may lead to duplicate generated classes with local (non-docker) Linux builds. -->
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using System.Net;
using HttpStress;
using System.Net.Quic;
using Microsoft.Quic;

[assembly:SupportedOSPlatform("windows")]
[assembly:SupportedOSPlatform("linux")]
Expand Down Expand Up @@ -186,23 +185,6 @@ private static async Task<ExitCode> Run(Configuration config)
Console.WriteLine("Query Parameters: " + config.MaxParameters);
Console.WriteLine();

if (config.HttpVersion == HttpVersion.Version30 && IsQuicSupported)
{
unsafe
{
// If the system gets overloaded, MsQuic has a tendency to drop incoming connections, see https://github.com/dotnet/runtime/issues/55979.
// So in case we're running H/3 stress test, we're using the same hack as for System.Net.Quic tests, which increases the time limit for pending operations in MsQuic thread pool.
object msQuicApiInstance = msQuicApiType.GetProperty("Api", BindingFlags.NonPublic | BindingFlags.Static).GetGetMethod(true).Invoke(null, Array.Empty<object?>());
QUIC_API_TABLE* apiTable = (QUIC_API_TABLE*)(Pointer.Unbox(msQuicApiType.GetProperty("ApiTable").GetGetMethod().Invoke(msQuicApiInstance, Array.Empty<object?>())));
QUIC_SETTINGS settings = default(QUIC_SETTINGS);
settings.IsSet.MaxWorkerQueueDelayUs = 1;
settings.MaxWorkerQueueDelayUs = 2_500_000u; // 2.5s, 10x the default
if (MsQuic.StatusFailed(apiTable->SetParam(null, MsQuic.QUIC_PARAM_GLOBAL_SETTINGS, (uint)sizeof(QUIC_SETTINGS), (byte*)&settings)))
{
Console.WriteLine($"Unable to set MsQuic MaxWorkerQueueDelayUs.");
}
}
}

StressServer? server = null;
if (config.RunMode.HasFlag(RunMode.server))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public class StressClient : IDisposable

public StressClient((string name, Func<RequestContext, Task> operation)[] clientOperations, Configuration configuration)
{
_cts.Token.Register(() =>
{
Console.WriteLine($"!!!Client cancellation invoked!!!");
});
_clientOperations = clientOperations;
_config = configuration;
_baseAddress = new Uri(configuration.ServerUri);
Expand Down Expand Up @@ -95,6 +99,7 @@ public void Start()

public void Stop()
{
Console.WriteLine($"Client cancellation issued from: {Environment.StackTrace}");
_cts.Cancel();
for (int i = 0; i < 60; ++i)
{
Expand Down Expand Up @@ -211,7 +216,7 @@ async Task RunWorker(int taskNum)
}
catch (Exception e)
{
_aggregator.RecordFailure(e, opIndex, stopwatch.Elapsed, requestContext.IsCancellationRequested, taskNum: taskNum, iteration: i);
_aggregator.RecordFailure(e, opIndex, stopwatch.Elapsed, requestContext.IsCancellationRequested, _cts.IsCancellationRequested, taskNum: taskNum, iteration: i);
}
}

Expand All @@ -230,12 +235,12 @@ private sealed class StressFailureType
// Representative error text of stress failure
public string ErrorText { get; }
// Operation id => failure timestamps
public Dictionary<int, List<(DateTime timestamp, TimeSpan duration, bool isCancelled)>> Failures { get; }
public Dictionary<int, List<(DateTime timestamp, TimeSpan duration, bool isCancelled, bool ctsState)>> Failures { get; }

public StressFailureType(string errorText)
{
ErrorText = errorText;
Failures = new Dictionary<int, List<(DateTime timestamp, TimeSpan duration, bool isCancelled)>>();
Failures = new Dictionary<int, List<(DateTime timestamp, TimeSpan duration, bool isCancelled, bool ctsState)>>();
}

public int FailureCount => Failures.Values.Select(x => x.Count).Sum();
Expand Down Expand Up @@ -280,7 +285,7 @@ public void RecordCancellation(int operationIndex, TimeSpan elapsed)
_latencies.Add(elapsed.TotalMilliseconds);
}

public void RecordFailure(Exception exn, int operationIndex, TimeSpan elapsed, bool isCancelled, int taskNum, long iteration)
public void RecordFailure(Exception exn, int operationIndex, TimeSpan elapsed, bool isCancelled, bool ctsState, int taskNum, long iteration)
{
DateTime timestamp = DateTime.Now;

Expand All @@ -301,13 +306,13 @@ void RecordFailureType()

lock (failureType)
{
if(!failureType.Failures.TryGetValue(operationIndex, out List<(DateTime timestamp, TimeSpan duration, bool isCancelled)>? details))
if (!failureType.Failures.TryGetValue(operationIndex, out List<(DateTime timestamp, TimeSpan duration, bool isCancelled, bool ctsState)>? details))
{
details = new List<(DateTime timestamp, TimeSpan duration, bool isCancelled)>();
details = new List<(DateTime timestamp, TimeSpan duration, bool isCancelled, bool ctsState)>();
failureType.Failures.Add(operationIndex, details);
}

details.Add((timestamp, elapsed, isCancelled));
details.Add((timestamp, elapsed, isCancelled, ctsState));
}

(Type exception, string message, string callSite)[] ClassifyFailure(Exception exn)
Expand Down Expand Up @@ -335,7 +340,7 @@ void PrintToConsole()
lock (Console.Out)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"Error from iteration {iteration} ({_operationNames[operationIndex]}) in task {taskNum} with {_successes.Sum()} successes / {_failures.Sum()} fails:");
Console.WriteLine($"Error from iteration {iteration} ({_operationNames[operationIndex]}) in task {taskNum}, cancelled: {isCancelled}, is stop issues: {ctsState}, duration: {elapsed} with {_successes.Sum()} successes / {_failures.Sum()} fails:");
Console.ResetColor();
Console.WriteLine(exn);
Console.WriteLine();
Expand Down Expand Up @@ -447,7 +452,7 @@ public void PrintFailureTypes()
Console.WriteLine(failure.ErrorText);
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Yellow;
foreach (KeyValuePair<int, List<(DateTime timestamp, TimeSpan duration, bool isCancelled)>> operation in failure.Failures)
foreach (KeyValuePair<int, List<(DateTime timestamp, TimeSpan duration, bool isCancelled, bool ctsState)>> operation in failure.Failures)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write($"\t{_operationNames[operation.Key].PadRight(30)}");
Expand All @@ -456,7 +461,7 @@ public void PrintFailureTypes()
Console.Write("Fail: ");
Console.ResetColor();
Console.Write(operation.Value.Count);
Console.WriteLine($"\t{string.Join(", ", operation.Value.Select(x => $"Timestamps: {x.timestamp:HH:mm:ss.fffffff}, Duration: {x.duration}, Cancelled: {x.isCancelled}"))}");
Console.WriteLine($"\t{string.Join(", ", operation.Value.Select(x => $"Timestamps: {x.timestamp:HH:mm:ss.fffffff}, Duration: {x.duration}, Cancelled: {x.isCancelled}, Stop Issued: {x.ctsState}"))}");
}

Console.ForegroundColor = ConsoleColor.Cyan;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ ARG VERSION=8.0
ARG CONFIGURATION=Release

RUN dotnet build -c $env:CONFIGURATION `
-p:MsQuicInteropIncludes="C:/live-runtime-artifacts/msquic-interop/*.cs" `
-p:TargetingPacksTargetsLocation=C:/live-runtime-artifacts/targetingpacks.targets `
-p:MicrosoftNetCoreAppRefPackDir=C:/live-runtime-artifacts/microsoft.netcore.app.ref/ `
-p:MicrosoftNetCoreAppRuntimePackDir=C:/live-runtime-artifacts/microsoft.netcore.app.runtime.win-x64/$env:CONFIGURATION/
Expand Down