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

Improve performance of Debugger.NotifyOfCrossThreadDependency under a debugger #101864

Merged
merged 4 commits into from
May 7, 2024

Conversation

davmason
Copy link
Member

@davmason davmason commented May 3, 2024

Fixes #38736

Currently the filtering for whether or not we send notifications lives on the ICorDebug side, which means for every call when a debugger is attached we do all the work to pause the runtime and send an IPC event. This changes the filtering to happen on the runtime side and only send an IPC event if the debugger wants to receive it.

Running the perf test from here: #38736 (comment) on my development machine I get the following results for a speedup of ~40x.

Before (Debugger)   : 19.7009k op/s
Before (No Debugger): 5879.8592k op/s

After  (Debugger)   : 777.8416k op/s
After  (No Debugger): 6044.5201k op/s

@davmason davmason added this to the 9.0.0 milestone May 3, 2024
@davmason davmason requested a review from a team May 3, 2024 21:13
@davmason davmason self-assigned this May 3, 2024
Copy link
Member

@noahfalk noahfalk left a comment

Choose a reason for hiding this comment

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

Your hashtable definition has some optional features enabled that are unneeded, but otherwise looks great!

src/coreclr/debug/ee/debugger.h Outdated Show resolved Hide resolved
src/coreclr/debug/ee/debugger.h Outdated Show resolved Hide resolved
src/coreclr/debug/ee/debugger.h Outdated Show resolved Hide resolved
Copy link
Member

@mikelle-rogers mikelle-rogers left a comment

Choose a reason for hiding this comment

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

I have a couple of questions.


bool IsNull() const
{
return m_module == NULL && m_typeDef == 0;
Copy link
Member

Choose a reason for hiding this comment

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

Why is there an && here instead of an ||?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have && because the NULL TypeInModule is defined as a NULL m_module pointer and a 0 m_typeDef. If one of them is true but not the other, it means that something has created a TypeInModule with invalid data, which is different than a NULL TypeInModule. We shouldn't ever see one or the other, only both


INT32 Hash() const
{
return (INT32)((UINT_PTR)m_module ^ m_typeDef);
Copy link
Member

Choose a reason for hiding this comment

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

Why did you choose to use this hash function?

Copy link
Member Author

Choose a reason for hiding this comment

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

For a hash function you want it to be quick to calculate, and also relatively unique to each entry. This is very quick to compute and should be unique most of the time. On 64 bit platforms there is a very low chance that the lower 32 bits of a module could be the same as another module and the typeDef could be repeated.

@davmason davmason merged commit 7dc3669 into dotnet:main May 7, 2024
87 checks passed
@noahfalk
Copy link
Member

noahfalk commented May 7, 2024 via email

@gaoyang
Copy link

gaoyang commented May 7, 2024

Looking forward to experiencing the results immediately 🎉

@akirayamamoto
Copy link

Consider back-porting this fix to DotNet 8 since DotNet 9 is a not a LTS release.

@noahfalk
Copy link
Member

noahfalk commented May 7, 2024

We wouldn't generally backport performance improvements (even large ones). Part of that is mitigating risk that we introduce a new bug in the servicing release and part is that time spent backporting changes to past releases is time not spent making other improvements. We can certainly see what other feedback we get on this though - its not a foregone conclusion.

In the meantime for many .NET apps you can successfully roll them forward to a new version of .NET runtime without needing to change code or rebuild. Even if you stay on an LTS version for shipping an app that shouldn't mean you are constrained to only debug using that same runtime version.

michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Jun 6, 2024
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.

Debugger.NotifyOfCrossThreadDependency can be slow when a debugger is attached
5 participants