-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Make Uri Thread-Safe #33042
Make Uri Thread-Safe #33042
Conversation
Uri tests in CI are hitting this assert in threads.cpp. @jkotas can you comment on what that is about? |
This assert means that lock was taken when thread exited. Your change might have exposed a bug somewhere else. |
Presumably it's because of this line in the test? |
Yes, this change would trigger this assert. This assert is a left-over from SQL CLR days where it was important to avoid orphaned locks. I will look into deleting it. |
|
070bdba
to
5ffd0d0
Compare
The scope of this PR has changed to Uri thread safety as a whole, not just the lock-on-string behavior. |
These APIs were introduced recently in dotnet/runtime#33042 and already used in several places e.g. in `Task`, `InterlockedBitVector32`, `SafeHandle`, `RegexCharClass` It should emit `%reg = atomicrmw and (or)` in LLVM IR. (and unlike `Interlocked.Add` these API return old value, see dotnet/runtime#33102 Addresses dotnet/runtime#32239 for Mono.
These APIs were introduced recently in dotnet/runtime#33042 and already used in several places e.g. in `Task`, `InterlockedBitVector32`, `SafeHandle`, `RegexCharClass` It should emit `%reg = atomicrmw and (or)` in LLVM IR. (and unlike `Interlocked.Add` these API return old value, see dotnet/runtime#33102 Addresses dotnet/runtime#32239 for Mono. Co-authored-by: EgorBo <[email protected]>
5ffd0d0
to
6959a92
Compare
*A lock may still be used for custom parsers
@stephentoub could you take a look at these changes? The gist of this change is
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good. Have you measured perf impact of constructing and initializing Uris?
6959a92
to
a577aae
Compare
I'm seeing a ~3% time improvement on the following test cases [Benchmark]
public int NewUri_Port() => new Uri("https://microsoft.com").Port;
[Benchmark]
public Uri NewUri_WithUnicode() => new Uri("https://microsoft.com/ä"); |
Thanks. |
Co-authored-by: Stephen Toub <[email protected]>
Fixes #19130, contributes to #24239 (I will update the docs after we ensure thread-safety across all members).
Instead of locking on a string (could have even been the same instance the user passed into the ctor) and on the
_info
, we can perform the necesarry synchronization around Flags by using Interlocked.UriInfo
andMoreInfo
fields are updated without synhronization, meaning that we may perform some duplicated work but not corrupt the state, The fields are always assigned-only in one go / written to before we share the instance (for example, we will set someUriInfo.Offset
fields before saving the local instance to the shared_info
field),