') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Unload MsQuic after checking for QUIC support to free resources. by rzikm · Pull Request #74749 · dotnet/runtime · GitHub
Skip to content

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

Merged
rzikm merged 3 commits into
dotnet:mainfrom
rzikm:74629-HttpClient-creates-Quic-threads-even-if-HTTP3-is-not-in-use
Sep 1, 2022
Merged

Unload MsQuic after checking for QUIC support to free resources.#74749
rzikm merged 3 commits into
dotnet:mainfrom
rzikm:74629-HttpClient-creates-Quic-threads-even-if-HTTP3-is-not-in-use

Conversation

@rzikm

@rzikmrzikm commented Aug 29, 2022

Copy link
Copy Markdown
Member

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:

usingSystem.Net.Http;HttpClientclient=newHttpClient();awaitclient.GetAsync("https://www.microsoft.com");System.Console.WriteLine("Done");System.Console.ReadLine();

Results on Windows11

DiffBeforeAfter
Threads6223
PrivateMemorySize1338572812083200

@ghostghost assigned rzikmAug 29, 2022
@ghost

Copy link
Copy Markdown

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
Copy Markdown
MemberAuthor

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
Copy Markdown
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:

internalstaticexternintMsQuicOpenVersion([NativeTypeName("uint32_t")]uintVersion,[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 wfurtAugust 29, 2022 12:11
@ManickaP

Copy link
Copy Markdown
Member

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

@rzikm

Copy link
Copy Markdown
MemberAuthor

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.

@wfurtwfurt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@ManickaPManickaP left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, modulo some nits.

}

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

private readonly?


try
{
// check version

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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:

internalstaticexternintMsQuicOpenVersion([NativeTypeName("uint32_t")]uintVersion,[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:mainSep 1, 2022
@rzikm

rzikm commented Sep 1, 2022

Copy link
Copy Markdown
MemberAuthor

/backport to release/7.0

@github-actions

Copy link
Copy Markdown
Contributor

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

@rzikm

rzikm commented Sep 2, 2022

Copy link
Copy Markdown
MemberAuthor

Reverted by #74984

@karelzkarelz 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
@ghostghost locked as resolved and limited conversation to collaborators Oct 3, 2022
Sign up for freeto 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

@rzikm@ManickaP@wfurt@karelz