-
Notifications
You must be signed in to change notification settings - Fork 15.6k
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
New Span-based C# parsing logic #7351
New Span-based C# parsing logic #7351
Conversation
this is still WIP and I'll probably do some rebasing, but all this seems to be the minimal PR that adds ReadOnlySequence parsing. |
54f5533
to
4e01423
Compare
Changes to fix running on .NET Framework: |
/// Internal implementation of merging data from given parse context into this message. | ||
/// Users should never invoke this method directly. | ||
/// </summary> | ||
void MergeFrom_Internal(ref ParseContext ctx); |
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 not a big fan of _Internal
suffix.
I'd rather it just be MergeFrom, have this comment warning that this overload of MergeFrom shouldn't be used, and code generation should explicitly implement the interface method.
https://hackernoon.com/hiding-members-via-explicit-interface-implementation-in-c-2c5u3oc1
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.
What are your plans for message writing? WriteContext and an equivalent method here?
I wonder if IBufferMessage is still the right name for this interface.
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 think MergeFromInternal and InternalMergeFrom also works.
Explicitly implementing the interface in generated code sounds like a good idea - I'll try that.
For message writing I think we can use a similar approach (which will hopefully require way fewer code changes than parsing). I think serialization could go in as a follow-up PR to make this PR smaller (we can make sure we won't release the intermediate version)
Do you have suggestions for how IBufferMessage should be renamed?
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.
Comments from looking through code with test coverage. Need to have some tests with legacy message generation to hit backwards compatibility paths.
} | ||
} | ||
|
||
state.totalBytesRetired += state.bufferSize; |
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.
FYI no tests reach here
/// </summary> | ||
internal bool DiscardUnknownFields { | ||
get { return state.DiscardUnknownFields; } | ||
set { state.DiscardUnknownFields = value; } |
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.
Is this set ever used? It is, just not used in tests
internal ExtensionRegistry ExtensionRegistry | ||
{ | ||
get { return state.ExtensionRegistry; } | ||
set { state.ExtensionRegistry = value; } |
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.
Is this set ever used? It is, just not used in tests
{ | ||
return 0F; | ||
} | ||
int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; |
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.
FYI no tests reach here
{ | ||
return 0D; | ||
} | ||
int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; |
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.
FYI no tests reach here
@gerben-s sorry, the commentary on benchmark results was buried in the comment thread: In short, the results seem to be pretty acceptable, especially because for C# we haven't really been too stringent about C# performance measurements until now (many of the benchmarks have only been added very recently) and we've demonstrated that being able to parse from ReadOnlySequence means a big improvement in terms of avoiding buffer copies and reducing GC pressure (so slight regression for some benchmarks would be trade off worth taking). |
Note that one benefit not shown by the benchmark results is the cost of creating the array when using Reading from a sequence (the newly added feature) allows parsing a third-party buffer of data, e.g. the request stream. That avoids overhead of allocations, copying and garbage collection. |
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 not the best person for c# review on code/style. However the high level structure seems very familiar and good to me. If the benchmarks are good as you say I think this is a great improvement
@jskeet do you have any more comments beyond what's been said above? If you want to take some more time to review this, feel free to - there's no rush, just let me know. |
@jskeet please let me know if you're planning to review this or not. |
Test failures seem completely unrelated to C#. |
Thanks everyone for the reviews and for all the work to get things to this state. |
FTR @jskeet has discovered a problem with this PR.
We have some ideas for how to fix this (it will require an |
New Span-based serialization logic (followup for #7351)
…harp_new_parsing New Span-based C# parsing logic
…ffer_serialization New Span-based serialization logic (followup for protocolbuffers#7351)
A big refactor of C# parsing logic to allow parsing from ReadOnlySequence (which would allow parsing directly from the data as received on the wire without requiring to copy the buffers and thus reducing the GC pressure a lot).
Main changes:
This PR drops netstandard1.0 support (which doesn't support the Span type we need) and adds netstandard1.1 instead. The impact on supported platforms should be minimal (almost everyone supports netstandard2.0 these days anyway).
Basically this PR a new and simpler take on #5888 (which is much bigger, introduces much more code duplication and leads to bigger public API increase).