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

Async support for frame processor #10

Merged
merged 3 commits into from
Nov 21, 2021

Conversation

lkstz
Copy link
Contributor

@lkstz lkstz commented Nov 2, 2021

As discussed in #9, this PR adds async support to IFrameProcessor and its implementation FrameProcessor.

The API has been extended by two methods, which, as discussed in #9, take/return a ValueTask and ValueTask<T>.

/// <summary>
/// Handles receiving and sending frames on the given stream.
/// </summary>
/// <param name="stream">The stream to receive and send frames on</param>
/// <param name="notifyHandler">Function to invoke when a NOTIFY frame is received</param>
ValueTask HandleStreamAsync(Stream stream, Func<NotifyFrame, ValueTask<IList<SpoeAction>>> notifyHandler);

/// <summary>
/// Cancels processing on the given stream.
/// </summary>
/// <param name="stream">The stream to cancel</param>
ValueTask CancelStreamAsync(Stream stream);

To avoid code duplication, I've used a pattern which uses a flag argument for internal methods to determine if the methods should be called asynchronously or not.
More information on that pattern:

Having async methods also allows reading/writing the stream in an async manner, which further improves the performance, which is why I've included it in this PR.

For now, I've decided to not include CancellationToken overloads or default parameters for the async methods as this complicates things a lot, especially with the notifyHandler callback. In addition, we'd need to define when and how we'd safely cancel reading/writing from/to the stream.

As discussed in #9, using ValueTask and ValueTask<T> in netstandard2.0 requires adding a dependency to System.Threading.Tasks.Extensions. As I think the multi-targeting out of scope for this PR, I've not implemented anything regarding this topic.

@NickMRamirez
Copy link
Contributor

Apologies for the delay in merging this. I am spending some time studying up on async again, just to understand it better.

@NickMRamirez
Copy link
Contributor

I read up on async, including the links that you provided, then I reviewed the code and did some performance testing. Your code is all quite good and it performs much better than the synchronous version. I will merge this, and I've also added an async example to the "examples" folder that I will commit afterwards.

Thanks for this contribution!

@NickMRamirez NickMRamirez merged commit a0ecee2 into haproxytech:master Nov 21, 2021
@scrocquesel
Copy link

Your code is all quite good and it performs much better than the synchronous version. I will merge this, and I've also added an async example to the "examples" folder that I will commit afterwards.

You may read my old comment #7 (comment) on perf issues. The real bottleneck is not the async processing. The loop is sync anyway and it will wait for the handler. Making it async just frees the thread while waiting for the I/O. This is of little help if you increase the max connection.

If you want a real big up (10 times faster) you will have to rewrote the parsing logic. You may find some inspiration at https://github.com/inulogic/HAProxy.StreamProcessingOffload.AgentFramework.

Especially using I/O Pipeline and buffer will also allow to write "network" unit tests very easily. Was very usefull when HAproxy SPOE implementation was buggy.

@NickMRamirez
Copy link
Contributor

@scrocquesel Async definitely improves I/O performance because it frees up a thread to go back to the thread pool to service other calls. I wouldn't say this is of little help, but I understand you have advocated for using System.IO.Piplines to improve performance in other ways, so I've opened a new issues where we can share ideas on that topic: #12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants