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

Improve performance of ProtocolReader #20

Open
1 of 2 tasks
davidfowl opened this issue Dec 29, 2019 · 5 comments
Open
1 of 2 tasks

Improve performance of ProtocolReader #20

davidfowl opened this issue Dec 29, 2019 · 5 comments
Assignees
Labels
performance Performance enhancement

Comments

@davidfowl
Copy link
Owner

davidfowl commented Dec 29, 2019

There are a few things that can be done to improve the performance of the ProtocolReader:

  • - Store the last ReadResult from the PipeReader and synchronously parse the protocol while there's still a buffer around. This reduces call to ReadAsync/Advance.
  • - ProtocolReader currently uses an async state machine in ReadAsync per call, it could implement IValueTaskSource to amortize this cost and reuse the ProtocolReader itself to avoid the per operation allocation (this is tricky and should be done last)
@davidfowl davidfowl changed the title Remove allocations from ProtocolReader Improve performance of ProtocolReader Dec 30, 2019
@davidfowl davidfowl self-assigned this Dec 30, 2019
@davidfowl
Copy link
Owner Author

ProtocolReader currently uses an async state machine in ReadAsync per call, it could implement IValueTaskSource to amortize this cost and reuse the ProtocolReader itself to avoid the per operation allocation (this is tricky and should be done last)

Turns out this is hard because the IValueTaskSource can't use the result type (TResult). The method is generic but the type isn't. This is more complicated and would require a cache per TResult. As a best effort, the code tries to avoid the state machine when the buffer is there.

@davidfowl davidfowl added the performance Performance enhancement label Jan 2, 2020
@AlgorithmsAreCool
Copy link

Sorry for being nosy, but this is a fascinating repo.

What about a generic version of ProtocolReader?

It looks like the common case is to read the same type repeatedly, so perhaps it would be worthwhile to optimize for that case? You would be able to use IValueTaskSource<TResult> then and gain back some perf.

Also, how difficult is implementing IValueTaskSource<TResult> now that ManualResetValueTaskSourceCore<TResult> exsists?

@davidfowl
Copy link
Owner Author

davidfowl commented Jan 5, 2020

What about a generic version of ProtocolReader?

Funny, it used to be generic then it was made non generic. Maybe it makes sense to have both.

Also, how difficult is implementing IValueTaskSource now that ManualResetValueTaskSourceCore exsists?

Much easier than it used to be, but still not completely trivial.

@davidfowl
Copy link
Owner Author

One reason the generic reader was remove was to allow composing protocols like this

public async ValueTask<HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, HttpCompletionOption completionOption = HttpCompletionOption.ResponseHeadersRead)
. Http reads the header then reads the body and those end up being different message readers

@AlgorithmsAreCool
Copy link

Perhaps rename the non-generic version to "MultiProtocolReader" or something?

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

No branches or pull requests

2 participants