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

Unload MsQuic after checking for QUIC support to free resources. #74749

Conversation

rzikm
Copy link
Member

@rzikm rzikm commented Aug 29, 2022

Fixes #74629.

This PR unloads MsQuic library from the process after we check whether it is supported. This saves some resources when HTTP3 is not used (e.g. the server does not advertise HTTP3)

Test app:

using System.Net.Http;

HttpClient client = new HttpClient();

await client.GetAsync("https://www.microsoft.com");

System.Console.WriteLine("Done");
System.Console.ReadLine();

Results on Windows11

Diff Before After
Threads 62 23
PrivateMemorySize 13385728 12083200

@ghost
Copy link

ghost commented Aug 29, 2022

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #74629.

This PR unloads MsQuic library from the process after we check whether it is supported. This saves some resources when HTTP3 is not used (e.g. the server does not advertise HTTP3)

Author: rzikm
Assignees: -
Labels:

area-System.Net.Http

Milestone: -

NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle);

internal static bool TryOpenMsQuic(IntPtr msQuicHandle, out QUIC_API_TABLE* apiTable)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could alternatively use [LibraryImport] for MsQuicOpenVersion and MsQuicClose, it might clean up the code a bit at the cost of not being able to unload the lib from the process I think (if we care about that)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They already have imports in:

internal static extern int MsQuicOpenVersion([NativeTypeName("uint32_t")] uint Version, [NativeTypeName("const void **")] void** QuicApi);

I'm not an expert on this, but we control which version of libmsquic we're loading in TryLoadMsQuic and we do an attempt to load it that would not fail if the lib is not present. I'm not sure we can achieve the same with the import. Relevant history: #49973

Anyway, we might at least use nameof(MsQuicOpenVersion) from the generated interop. Though we lived with the string until now, so it's certainly not critical.

@rzikm rzikm marked this pull request as ready for review August 29, 2022 12:10
@rzikm rzikm requested review from ManickaP and wfurt August 29, 2022 12:11
@ManickaP
Copy link
Member

Are the threads started by opening MsQuic: MsQuicOpenVersion or by opening registration: RegistrationOpen?

@rzikm
Copy link
Member Author

rzikm commented Aug 29, 2022

Are the threads started by opening MsQuic: MsQuicOpenVersion or by opening registration: RegistrationOpen?

It is the MsQuicOpenVersion and MsQuicClose calls that change the number of threads visible.

Copy link
Member

@wfurt wfurt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@ManickaP ManickaP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, modulo some nits.

@@ -47,7 +48,8 @@ private MsQuicApi(QUIC_API_TABLE* apiTable)
}
}

internal static MsQuicApi Api { get; } = null!;
internal static Lazy<MsQuicApi> _api = new Lazy<MsQuicApi>(AllocateMsQuicApi);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private readonly?

{
return;
}

try
{
// check version
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uber nitty nit 😄

Suggested change
// check version
// Check version

throw new Exception("Failed to create MsQuicApi instance");
}

internal static bool TryLoadMsQuic(out IntPtr msQuicHandle) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should those be private?

NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle);

internal static bool TryOpenMsQuic(IntPtr msQuicHandle, out QUIC_API_TABLE* apiTable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They already have imports in:

internal static extern int MsQuicOpenVersion([NativeTypeName("uint32_t")] uint Version, [NativeTypeName("const void **")] void** QuicApi);

I'm not an expert on this, but we control which version of libmsquic we're loading in TryLoadMsQuic and we do an attempt to load it that would not fail if the lib is not present. I'm not sure we can achieve the same with the import. Relevant history: #49973

Anyway, we might at least use nameof(MsQuicOpenVersion) from the generated interop. Though we lived with the string until now, so it's certainly not critical.

@rzikm rzikm merged commit 7a45201 into dotnet:main Sep 1, 2022
@rzikm
Copy link
Member Author

rzikm commented Sep 1, 2022

/backport to release/7.0

@github-actions
Copy link
Contributor

github-actions bot commented Sep 1, 2022

Started backporting to release/7.0: https://github.com/dotnet/runtime/actions/runs/2972591441

@rzikm
Copy link
Member Author

rzikm commented Sep 2, 2022

Reverted by #74984

@karelz karelz added this to the 8.0.0 milestone Sep 3, 2022
wfurt added a commit that referenced this pull request Sep 6, 2022
wfurt added a commit that referenced this pull request Sep 8, 2022
* Revert "Revert "Unload MsQuic after checking for QUIC support to free resources. (#74749)" (#74984)"

This reverts commit 953f524.

* update helix images

* update helix images

* Improve diagnostics when opening MsQuic

Co-authored-by: Radek Zikmund <radekzikmund@microsoft.com>
rzikm added a commit to rzikm/dotnet-runtime that referenced this pull request Sep 9, 2022
…et#75163)

* Revert "Revert "Unload MsQuic after checking for QUIC support to free resources. (dotnet#74749)" (dotnet#74984)"

This reverts commit 953f524.

* update helix images

* update helix images

* Improve diagnostics when opening MsQuic

Co-authored-by: Radek Zikmund <radekzikmund@microsoft.com>
rzikm added a commit to rzikm/dotnet-runtime that referenced this pull request Sep 13, 2022
…et#75163)

* Revert "Revert "Unload MsQuic after checking for QUIC support to free resources. (dotnet#74749)" (dotnet#74984)"

This reverts commit 953f524.

* update helix images

* update helix images

* Improve diagnostics when opening MsQuic

Co-authored-by: Radek Zikmund <radekzikmund@microsoft.com>
carlossanlop pushed a commit that referenced this pull request Sep 23, 2022
…sources (#75163, #75441) (#75521)

* Unload MsQuic after checking for QUIC support to free resources (#75163)

* Revert "Revert "Unload MsQuic after checking for QUIC support to free resources. (#74749)" (#74984)"

This reverts commit 953f524.

* update helix images

* update helix images

* Improve diagnostics when opening MsQuic

Co-authored-by: Radek Zikmund <radekzikmund@microsoft.com>

* Don't unload MsQuic from the process (#75441)

* Revert helix queues change (to be done in another PR)

* Code review feedback
@ghost ghost locked as resolved and limited conversation to collaborators Oct 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HttpClient creates Quic threads even if HTTP/3 is not in use
4 participants