-
Notifications
You must be signed in to change notification settings - Fork 1.3k
CSHARP-5496: Reduce locks contention on server selection and connection checkout #1617
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
private ClusterDescription _description; | ||
private TaskCompletionSource<bool> _descriptionChangedTaskCompletionSource; | ||
private readonly object _descriptionLock = new object(); | ||
private Tuple<ClusterDescription, TaskCompletionSource<bool>> _descriptionWithChangedTaskCompletionSource; |
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.
I've decided to use Tuple instead of 2 fields, to let me remove lock in UpdateClusterDescription
method.
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.
This change looks good!
oldClusterDescription = _description; | ||
_description = newClusterDescription; | ||
var oldClusterDescription = Interlocked.Exchange(ref _descriptionWithChangedTaskCompletionSource, | ||
Tuple.Create(newClusterDescription, new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously))); |
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.
We can use TaskCreationOptions.RunContinuationsAsynchronously
and remove old workaround with explicitly running new task (see line 311 before the changes).
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.
minor: new(newClusterDescription, new(TaskCreationOptions..))
?
TrackInUseConnection(result); | ||
} | ||
|
||
// This connection can be expired and not disposed by Prune. Dispose if needed |
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.
It looks like there is no way to get expired connection here, because we just checked that in line 763.
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.
Just a few minor comments for your consideration.
private ClusterDescription _description; | ||
private TaskCompletionSource<bool> _descriptionChangedTaskCompletionSource; | ||
private readonly object _descriptionLock = new object(); | ||
private Tuple<ClusterDescription, TaskCompletionSource<bool>> _descriptionWithChangedTaskCompletionSource; |
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.
This change looks good!
_clusterId = new ClusterId(); | ||
_description = ClusterDescription.CreateInitial(_clusterId, _settings.DirectConnection); | ||
_descriptionChangedTaskCompletionSource = new TaskCompletionSource<bool>(); | ||
_descriptionWithChangedTaskCompletionSource = new(ClusterDescription.CreateInitial(_clusterId, _settings.DirectConnection), new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously)); |
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.
minor:
_descriptionWithChangedTaskCompletionSource = new(ClusterDescription.CreateInitial(_clusterId, _settings.DirectConnection), new(TaskCreationOptions.RunContinuationsAsynchronously));
oldClusterDescription = _description; | ||
_description = newClusterDescription; | ||
var oldClusterDescription = Interlocked.Exchange(ref _descriptionWithChangedTaskCompletionSource, | ||
Tuple.Create(newClusterDescription, new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously))); |
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.
minor: new(newClusterDescription, new(TaskCreationOptions..))
?
|
||
// TODO: use RunContinuationsAsynchronously instead once we require a new enough .NET Framework | ||
Task.Run(() => oldDescriptionChangedTaskCompletionSource.TrySetResult(true)); | ||
oldClusterDescription.Item2.TrySetResult(true); |
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.
Consider defining a 2 liner private class to improve readability of Item1
and Item2
.
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.
Done.
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.
Apart from the comments that Boris already gave, LGTM!
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.
LGTM!
} | ||
|
||
// nested classes | ||
internal class ClusterDescriptionChangeSource |
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.
nit: sealed.
|
||
public ClusterDescriptionChangeSource(ClusterDescription clusterDescription) | ||
{ | ||
_changedTaskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously); |
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.
Nice to hide this ceremony of source creation.
No description provided.