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

[NET_HANDLER] Considering replacing Protobuf with JSON #270

Open
benliao1 opened this issue Aug 1, 2023 · 3 comments
Open

[NET_HANDLER] Considering replacing Protobuf with JSON #270

benliao1 opened this issue Aug 1, 2023 · 3 comments
Labels
enhancement New feature or request

Comments

@benliao1
Copy link
Collaborator

benliao1 commented Aug 1, 2023

Currently, Runtime communicates with Dawn and Shepherd over the network using the Google Protobuf protocol. It is a highly optimized protocol to deliver a given amount of information over the network in as few bytes as possible. This is useful for large data centers (as Google has) where network loading is a real issue. However, the amount of data sent between Dawn, Runtime, and Shepherd is not that large, in the grand scheme of things.

PiE started using Google Protobuf at least since 2017 in order to try to lighten the load on the network during competition. We now know that the real issue with our networking was that the software projects (especially Shepherd and Runtime) were simply too unstable at the time.

One of Runtime's last big 3rd-party dependencies is Google Protobuf. The process for using Google Protobuf in C and compiling the C header files from source is quite cumbersome. Learning how to write protobuf code, on top of learning all of Runtime, is quite difficult, especially since there isn't much documentation of the protobuf-c library.

This issue is to consider changing the way that Runtime, Dawn, and Shepherd communicate with each other. Instead of using Google Protobuf, we simply use JSON, which has native support in Python and Javascript. C does not support it natively but the tools used to marshal / unmarshal JSON messages in C are tiny in comparison to those needed to work with Protobuf.

This would remove the last huge third-party dependency from Runtime and make it nearly completely self-contained. However, it would require a lot of coordination between all 3 of PiE's software projects to pull off.

@benliao1 benliao1 added the enhancement New feature or request label Aug 1, 2023
@sberkun
Copy link

sberkun commented Aug 1, 2023

As someone from Shepherd, I am in favor. Protobufs are overkill for Pie's use case, and caused Shepherd some pain last January when the Python protobuf library was broken.

My only concern is that this will cause the message definitions to become more informal. One advantage of protobuf is that (for example) both Dawn and Runtime members can look at input.proto and see exactly what an input message is supposed to contain. If we switch to JSON there's a temptation to pass the "schema" by word of mouth.

We could create a wiki page that contains "definitions" like this:

// message type: 1
UserInputs = {
    "inputs": [Input, ...]
}
Input = {
    "connected": bool,
    "buttons": double,
    "axes": [double, double, double],
    "source": "gamepad" | "keyboard"
}

but there's nothing that forces such a page to stay up-to-date or accurate.

@benliao1
Copy link
Collaborator Author

@sberkun Do you think we could still maintain a Github repo with all of the message definitions in there, and import it as a submodule into Dawn, Shepherd, and Runtime? That way there's no confusion for what the scheme is--the single source of truth is that repo. I suppose there's no way of ensuring that someone doesn't change the code without updating the repo but at that point they're almost breaking it on purpose, right?

@sberkun
Copy link

sberkun commented Aug 16, 2023

perhaps; I'm still worried that the submodule might go ignored, and new members start writing code without realizing that it exists.

To make it more enforcable, maybe the serialization/deserialization code for all 3 teams should also be in the submodule. For example, Shepherd's code would look something like:

class UserInputs:
    def __init__(self, msg):
        obj = json.loads(msg)
        self.inputs = [Input(ob) for ob in obj["inputs"]]

class Input:
    GAMEPAD = "gamepad"
    KEYBOARD = "keyboard"
    def __init__(self, obj):
        self.connected = obj["connected"]
        self.buttons = obj["buttons"]
        self.axes = obj["axes"]
        self.source = obj["source"]

Then whenever an update needs to be made, the schema and code for all 3 teams can be updated in a single PR.

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

No branches or pull requests

2 participants