Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Improve UnwindInfoTable's performance - #125545

Merged
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject
Mar 20, 2026
Merged

Improve UnwindInfoTable's performance#125545
eduardo-vp merged 24 commits into
dotnet:mainfrom
eduardo-vp:lock-per-UnwindInfoTableObject

Conversation

@eduardo-vp

@eduardo-vpeduardo-vp commented Mar 14, 2026

Copy link
Copy Markdown
Member

Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of RUNTIME_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

CopilotAI review requested due to automatic review settings March 14, 2026 01:29

This comment was marked as outdated.

@eduardo-vp
eduardo-vpforce-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6CompareMarch 17, 2026 02:05
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vpeduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lockImprove UnwindInfoTable's performanceMar 17, 2026
CopilotAI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

Storing in a buffer and flushing with two locks actually led to better performance of the test case mentioned in #123124 (comment).

ChangeTime
Main~580 ms
Buffer + flush with 2 locks~200 ms

CopilotAI review requested due to automatic review settings March 20, 2026 00:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:1

  • Removal only searches the published table and ignores entries that are still in the pending buffer. If a method is unpublished before its unwind data is flushed, the pending entry can later be published to the OS (stale unwind info), and removal will incorrectly report not found. Fix by also searching/removing matching entries from the pending buffer under s_pUnwindInfoTablePendingLock (and/or forcing a flush before attempting removal) so unpublish is correct regardless of whether the entry was already published.
// Licensed to the .NET Foundation under one or more agreements.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/codeman.cpp
@jkotas

Copy link
Copy Markdown
Member

What does the perf look like with the latest delta?

@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

These are the results with the latest changes

BranchTest execution time
Main~580 ms
Current~198 ms

@AaronRobinsonMSFTAaronRobinsonMSFT 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.

Two nits I'd personally like to see fix, but other than that, LGTM. Thanks!

Comment threadsrc/coreclr/vm/codeman.cpp Outdated
Comment threadsrc/coreclr/vm/codeman.cpp
CopilotAI review requested due to automatic review settings March 20, 2026 05:22

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/codeman.cpp
Comment threadsrc/coreclr/vm/codeman.cpp
@eduardo-vp

Copy link
Copy Markdown
MemberAuthor

/ba-g unrelated failure

@eduardo-vp
eduardo-vp merged commit 43502e5 into dotnet:mainMar 20, 2026
101 of 105 checks passed
@agocke

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@agocke backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Batch unwind info table entriesApplying: Flush before method is done JITingApplying: Use two lockserror: sha1 information is lacking or useless (src/coreclr/vm/codeman.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Use two locksError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@agocke

Copy link
Copy Markdown
Member

@eduardo-vp Could you port this over manually? The automation seems to be having issues.

eduardo-vp added a commit to eduardo-vp/runtime that referenced this pull request Mar 30, 2026
Place the entries of UnwindInfoTable in a buffer and flush such that we amortize the cost of the operations (pRtlAddGrowableFunctionTable + pRtlDeleteGrowableFunctionTable) to create the internal table of `RUNTIME_FUNCTION`s.
Contributes to dotnet#123124.
---------
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
agocke pushed a commit that referenced this pull request Apr 22, 2026
Backport of #125545 to release/10.0
Place the entries of UnwindInfoTable in a buffer and flush such that we
amortize the cost of the operations (pRtlAddGrowableFunctionTable +
pRtlDeleteGrowableFunctionTable) to create the internal table of
`RUNTIME_FUNCTION`s.
## Customer Impact
- [x] Customer reported
- [ ] Found internally
Regression was reported in
#123124.
## Regression
- [X] Yes
- [ ] No
## Testing
Tested with the following test case in
#123124 (comment)
and execution time was reduced in 50%. Also, all tests in CI passed.
## Risk
Medium. The change affects x64 windows programs and the changes are not
trivial.
Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 30, 2026
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.

5 participants

@eduardo-vp@jkotas@agocke@AaronRobinsonMSFT