-
Notifications
You must be signed in to change notification settings - Fork 595
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
Code cleanups and performance optimizations. #1017
Conversation
@bollhals might want to take a look as well. |
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.
Looking good to me. Question is though, what will remain in Protocol class? It seems to slowly die out.
} | ||
|
||
if (!_closeServerInitiated && frame.Type == FrameType.FrameMethod) | ||
if (_closing) |
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.
can we switch the common case first?
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.
That'll involve doing a lot more checks really. This just does the first check on if _closing
which is almost always false and then just continues to the transmit. This usually compiles to no code jumping unless the if matches which is usually faster.
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 expect this to be cheaper than acquiring a lock either way ;)
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 for sure =)
A quick "is null" check might be as fast as a enum compare 🤔
Yes. The Protocol class seems redundant to me. I can see what the point of it was but extending the client with a new protocol other than AMQP 0.9.8 is a much bigger task than just adding a new protocol. Is there a reason to keep the protocol abstraction around @michaelklishin? Seems like it'd be easier to write a new client for a new protocol than to support more than one in the current client. |
Sounds reasonable to me. |
This looks reasonable, thank you. Any benchmarks that demonstrate the improvement for some key workloads? |
I'll see if I can do some benchmarks. They are a bit harder to do here since they require actual usages of Connection/Model objects. |
{ | ||
if (!_closing) | ||
lock (this) |
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.
In general it is not a good practice to lock on this since this can lead to deadlocks because your are locking the whole instance on which someone external could also lock on. Either bring the lock instance object back or use a compare exchange spin approach?
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.
Sessions are internal objects not exposed in any way to the public. While I agree with the general statement, I think one does not always have to follow it if the lock from outside is not possible.
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.
Yeah, I know locking on the instance is not recommended but in this case we can be sure that no one external will lock on it, unless through reflection gymnastics but all bets are off at that point anyway.
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'm a fan of least surprises. Even for internal usage. It doesn't necessarily have to be user code. Sometimes over time things slip in. Having a dedicated lock is the safer choice. Yet I'm not hung up on it. Feel free to ignore
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 add a new field just for locking. One more object per connection is not going to make much of a difference.
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.
Should we do this?
Given that the gain is 0,1% or so, do we want to proceed with this solely for code simplification (if any) or just close it? We obviously appreciate the time @stebet and the reviewers have put into this PR. But if an optimization PR doesn't make any difference to benchmarks in the end, is it worth adopting? |
I'm biased, this being my PR and all, but from a code cleaning perspective I'd say yes. The performance optimization was purely a bonus and not the main point of the PR, although less locking is always better too. Although throughput gains were minimal, CPU usage also dropped a bit as a result. |
At this point, we can just drop it and leave only 0-9-1 as supported. 0-8 and 0-9 share a lot with 0-9-1 (unlike 1.0, which is a completely different protocol), so years ago it made sense to support them all. 0-9-1 is available in RabbitMQ 2.0+, which has been out for more than a decade. So we can remove all 0-8 and 0-9 bits (I don't expect there to be many) in a separate PR. |
Proposed Changes
Removing some redundant code and some performance optimizations.
Types of Changes
Checklist
CONTRIBUTING.md
document