-
-
Notifications
You must be signed in to change notification settings - Fork 116
Improved locking performance on .NET 9.0+ #1532
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
Conversation
|
Thanks for filing the PR. Good to know that We could do the same via: #if NET_9_0_OR_GREATER
private readonly Lock syncLock = new();
#else
private readonly object syncLock = new();
#endifMaybe @egil, and I can discuss this next week, but I would drop the package in favor of the more simple approach - given that we don't have many places where we are using locks. |
|
Hi @linkdotnet, I didn't quite expect a comment from the guy whose blog articles helped inspire this micro-library. Thanks for that! Yes, such an approach as you mentioned is possible, however as you are well aware of, |
Thanks for the mention and also linking the blog post as motivation for the PR.
I am not sure if I understand 100% here. Let's dissect this a bit. We basically have two scenarios:
For the first one, sure -
Why is that? Until |
|
OK let's say you have a Lock instance and you have one method that's doing a lock (myObj) on it. That will work with the trick you posted above. So far so good. Now let's say you add a second method but want to have a timeout on it. Now you can neither use myObj.Enter(5) because on .NET 8.0 that won't work, nor can you use Monitor.Enter(myObj, 5) because on .NET 9.0 that has different behaviour. Remember the new locking class doesn't use Monitor, so if you try this your lock for the timeout and the normal lock (myObj) will behave as if they were two different locks, apart from not getting the performance improvement on .NET 9.0. |
|
Basically: private readonly Lock myObj = new();
void DoThis()
{
lock (myObj)
{
// do something
}
}
void DoThat()
{
myObj.Enter(5); // this will not compile on .NET 8.0
Monitor.Enter(myObj, 5); // this will immediately enter the lock on .NET 9.0 even if another thread is locking on DoThis()
// do something else
} |
Doesn't even stop here :) |
The only limitation is that on .NET Framework 3.5 and .NET Framework 4.0, you cannot use the |
|
Okay now I understand a bit better - thanks for clarifying @MarkCiliaVincenti !
True that - and here is what I meant initially. If we have such a situation, I totally agree, that some kind of backport is useful! The way bUnit is using locking is very simple and we don't have such cases. So my argument would still be: For now, I would postpone the usage of a micro-library for a case we don't have and use it once we hit this barrier. Don't get me wrong: You did an amazing job, and lots of folks have such use cases, but bUnit doesn't (at the moment). |
Fair enough. .NET FX 4.0 isn't supported anymore anyway. So targeting |
That is correct. It will work as per the code you wrote. There's also a neater way of doing it via: And if you do try to Monitor.Enter on it, it will still give you the warning CS9216: A value of type System.Threading.Lock converted to a different type will use likely unintended monitor-based locking in lock statement. That said, I understand your argument with regards to crossing the bridge when you come to it, but it just feels a bit like procrastinating to me and I'd personally prefer to remove the limitation. If your biggest concern is adding in a new dependency, you may want to consider importing the class directly into your project, just giving some credit. |
It isn't about procrastinating or not - sorry if it felt that way. It is more about the choice we have to make to onboard something we have to maintain for years to come. Given that we support We will add a dependency for users, so we have to think through it and not just rush into something. I do understand that you have an awesome library that solves specific issues for users.
I do understand and also agree that your library might solve that for many folks. My whole argumentation is based on the fact, that we don't have such code. Given the pros and cons, what is the downside of delaying this to the time we are sure we will run into this situation? Or at least think of all the scenarios. |
|
After discussing (link)the pros and cons, we decided that for bUnit that we keep the current Thanks for filing the PR and discussing it! |
|
@linkdotnet a new version of Backport.System.Threading.Lock has come out that acts as a source generator and basically dropping the DLL as a dependency. If this new development makes you reconsider, I will amend this PR accordingly. |
|
Hey @MarkCiliaVincenti - cool that you invested time into making a SG. For me, nothing changes much here. It is somewhat in the same category as you proposed earlier:
But thanks again for bringing up the topic with the updated library of yours! |
The new System.Threading.Lock offers greater performance, as independent benchmarks show (eg https://steven-giesel.com/blogPost/4cf6d48a-ec9d-4c68-961c-31fd8d8c1340)