Skip to content

Improve UnwindInfoTable's performance#125545

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

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

Conversation

@eduardo-vp
Copy link
Member

@eduardo-vp eduardo-vp commented Mar 14, 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_FUNCTIONs.

Contributes to #123124.

This comment was marked as outdated.

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

This comment was marked as outdated.

@eduardo-vp eduardo-vp force-pushed the lock-per-UnwindInfoTableObject branch from 75cd28d to 7358ca6 Compare March 17, 2026 02:05
@eduardo-vp eduardo-vp changed the title Use a lock per UnwindInfoTable object instead of global lock Improve UnwindInfoTable's performance Mar 17, 2026
Copilot AI review requested due to automatic review settings March 18, 2026 00:47

This comment was marked as outdated.

@eduardo-vp
Copy link
Member Author

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

Change Time
Main ~580 ms
Buffer + flush with 2 locks ~200 ms

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes CoreCLR’s Windows x64 unwind-info publishing by buffering RUNTIME_FUNCTION entries and batch-merging them into the OS growable function table, aiming to reduce overhead from frequent register/unregister operations during JIT.

Changes:

  • Introduces a per-UnwindInfoTable pending buffer and a FlushPendingEntries() path to batch-merge unwind entries.
  • Splits the single unwind-info lock into publish vs pending locks to reduce contention.
  • Updates Crst type definitions / generated mappings for the new lock types.

Reviewed changes

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

File Description
src/coreclr/vm/codeman.h Adds pending buffer fields and refactors APIs around buffered publishing.
src/coreclr/vm/codeman.cpp Implements pending-buffer accumulation, flush/merge logic, and new lock usage.
src/coreclr/inc/CrstTypes.def Defines UnwindInfoTablePublishLock and UnwindInfoTablePendingLock and their ordering.
src/coreclr/inc/crsttypes_generated.h Updates generated Crst enum/name/level maps to include new locks.
Comments suppressed due to low confidence (1)

src/coreclr/vm/codeman.cpp:489

  • PublishUnwindInfoForMethod calls AddToUnwindInfoTable(...) and then calls FlushPendingEntries(), but AddToUnwindInfoTable already flushes at the end of the batch. This adds an extra lock acquisition on the publish path; consider removing the extra flush or restructuring so flushing happens in only one place.
        unwindInfo->AddToUnwindInfoTable(methodUnwindData, methodUnwindDataCount);
    }
}

/*****************************************************************************/

Copilot AI review requested due to automatic review settings March 20, 2026 00:42
Copy link
Contributor

Copilot AI left a comment

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.

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copilot AI review requested due to automatic review settings March 20, 2026 00:58
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copy link
Contributor

Copilot AI left a comment

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.

@jkotas
Copy link
Member

jkotas commented Mar 20, 2026

What does the perf look like with the latest delta?

@eduardo-vp
Copy link
Member Author

These are the results with the latest changes

Branch Test execution time
Main ~580 ms
Current ~198 ms

Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

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!

Copilot AI review requested due to automatic review settings March 20, 2026 05:22
Copy link
Contributor

Copilot AI left a comment

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.

@eduardo-vp
Copy link
Member Author

/ba-g unrelated failure

@eduardo-vp eduardo-vp merged commit 43502e5 into dotnet:main Mar 20, 2026
101 of 105 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants