-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
[dotnet] [bidi] Revisit some core functionality to deserialize without intermediate JsonElement
allocation
#15575
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
[dotnet] [bidi] Revisit some core functionality to deserialize without intermediate JsonElement
allocation
#15575
Conversation
PR Reviewer Guide 🔍(Review updated until commit b560945)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to b560945
Previous suggestions✅ Suggestions up to commit 1a4773e
|
@RenderMichael finally ready for review, actually it simplifies the core functionality. Previously I tried to make remote end Please review changes in |
Going forward, truly internal stuff. I need it to make improvements further. |
CI fails not related to this PR, merging. |
Utf8JsonReader reader = new(new ReadOnlySpan<byte>(data)); | ||
reader.Read(); | ||
|
||
reader.Read(); // "{" |
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.
Debug.Assert(reader.TokenType == JsonTokenType.StartObject);
, to protect against future refactorings?
Or better yet, maybe we should throw in this case?
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.
Moving fast for now, revisit later as not important for end users.
case "message": | ||
message = reader.GetString(); | ||
break; | ||
} |
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.
default: throw new BiDiException($"Unexpected BiDi response: {Encoding.UTF8.GetString(data)}")
?
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.
yep, we will introduce handling of "unknown polymorphic types"
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.
Please post an issue to not forget, for now just moving fast to introduce good pattern for BiDi namespace
using System.Text.Json.Serialization; | ||
|
||
namespace OpenQA.Selenium.BiDi.Communication; | ||
|
||
public abstract class Command | ||
{ | ||
protected Command(string method) | ||
protected Command(string method, Type resultType) |
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.
Not related to this PR: what do you think of renaming this type BiDiCommand
? It is more clear and easier for namespacing (we already have a Command
type)
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.
No, I don't like any BiDi*
type in BiDi
namespace. Namespaces are especially created to resolve collisions.
@@ -46,3 +52,5 @@ internal record CommandParameters | |||
{ | |||
public static CommandParameters Empty { get; } = new CommandParameters(); | |||
} | |||
|
|||
public record EmptyResult; |
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.
Maybe BaseResult
or BiDiResult
? Since it is derived by results with values.
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.
Opened #15593
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.
Answered there, I prefer just Result
@@ -22,7 +22,7 @@ | |||
namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; | |||
|
|||
internal class CloseCommand(CloseCommandParameters @params) | |||
: Command<CloseCommandParameters>(@params, "browsingContext.close"); | |||
: Command<CloseCommandParameters, EmptyResult>(@params, "browsingContext.close"); |
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.
Empty result is used it mean two things in two different places: base result
and void result
. The same type serving two different purposes. I propose making this two different types. It will have a real advantage: today, EmptyResult
can be assigned a real results value. If we have a separate "no results" type, then it will be guaranteed safe.
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 will not have "no results" at all. Any command will return results, read it as public Task<Result> DoSomething()
.
User description
Core aspects:
MessageSuccess<T>
which will handleExtensible
payload (looking to the future)It is still in "dirty" state, but conceptually it becomes better.
🔗 Related Issues
💥 What does this PR do?
Improve memory allocation. Locating all
div
nodes on google.com: before404KB
, after317KB
.🔧 Implementation Notes
💡 Additional Considerations
🔄 Types of changes
PR Type
Enhancement
Description
Refactored BiDi commands to use strongly-typed results, improving deserialization efficiency.
Introduced
EmptyResult
as a base class for command results, simplifying result handling.Enhanced event handling with a new
_eventTypesMap
for dynamic event type resolution.Removed intermediate
JsonElement
allocations, optimizing memory usage.Replaced
int
withlong
for command IDs, ensuring compatibility with larger ranges.Changes walkthrough 📝
18 files
Refactored Broker to handle typed command results and events
Added result type to Command class for typed results
Updated serializer context for new result types
Updated Message records for typed results
Updated CloseCommand to use EmptyResult
Updated CreateUserContextCommand to use typed result
Updated GetClientWindowsCommand to use typed result
Updated GetUserContextsCommand to use typed result
Updated RemoveUserContextCommand to use EmptyResult
Updated ActivateCommand to use EmptyResult
Updated CaptureScreenshotCommand to use typed result
Updated CloseCommand to use EmptyResult
Updated CreateCommand to use typed result
Updated GetTreeCommand to use typed result
Updated HandleUserPromptCommand to use EmptyResult
Updated LocateNodesCommand to use typed result
Updated NavigateCommand to use typed result
Updated PrintCommand to use typed result
2 files
Removed unused MessageConverter class
Fixed typo in exception message
29 files