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

Serialize and deserialize protocol buffers #2667

Open
6 of 7 tasks
kyleconroy opened this issue Mar 3, 2022 · 12 comments
Open
6 of 7 tasks

Serialize and deserialize protocol buffers #2667

kyleconroy opened this issue Mar 3, 2022 · 12 comments
Labels
enhancement New feature or request

Comments

@kyleconroy
Copy link
Contributor

kyleconroy commented Mar 3, 2022

As outlined in #447, TinyGo should support common serialization formats. While most people may think of JSON, I personally want TinyGo to support protocol buffers. This issue is meant to track my progress on adding Protocol Buffer support to TinyGo.

Design

The default Protocol Buffer package (https://pkg.go.dev/google.golang.org/protobuf) makes heavy use of reflection. TinyGo only supports a small amount of the reflect package. Heavy use of reflection leads to slow code, so the folks at PlanetScale wrote vtprotobuf, which generates explicit serialization / deserialization code. This code works today with TinyGo. However, it requires the existing, slow code to compile.

So the plan is simple: Support compiling the code generated by protoc-gen-go and running and of the code contained in init() functions. Use the code generated by vtprotobuf to serialize and deserialize the data.

Roadmap

@paralin
Copy link
Contributor

paralin commented Mar 4, 2023

@kyleconroy This is a great idea, I'm using vtprotobuf a lot currently and it works great. Having some kind of auto-transpiler that automatically converts the reflection-based protobuf-go to use vtprotobuf would be great.

Quick question: as of March 2023, it seems like most of the reflection features are supported - is there anything missing for the existing reflection version to work currently?

@dgryski
Copy link
Member

dgryski commented Mar 23, 2023

And even more reflect is working, including the last bug on you roadmap.

@gitslav
Copy link

gitslav commented Jun 15, 2023

@kyleconroy @dgryski looking at the roadmap is it time for the confetti emoji?

@rockwotj
Copy link
Contributor

So it seems that the default protobuf compiler is not supported still even with the improvements to reflection. I have yet to test vtprotobuf

% ./wasmtime-v14.0.4-x86_64-linux/wasmtime run protobuf-example.wasm
panic: unimplemented: (reflect.Type).MethodByName()
Error: failed to run main module `protobuf-example.wasm`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
           0: 0x5a15 - <unknown>!runtime._panic
           1: 0x5939 - <unknown>!(reflect.rawType).MethodByName
           2: 0x6484 - <unknown>!(*reflect.rawType).MethodByName
           3: 0x103253 - <unknown>!(*google.golang.org/protobuf/internal/impl.MessageInfo).makeStructInfo
           4: 0xb95e6 - <unknown>!(*google.golang.org/protobuf/internal/impl.MessageInfo).init
           5: 0xb8e02 - <unknown>!google.golang.org/protobuf/proto.protoMethods
           6: 0x34c67 - <unknown>!(google.golang.org/protobuf/proto.MarshalOptions).marshal
           7: 0x2d45a - <unknown>!runtime.run$1
           8: 0x2cf76 - <unknown>!runtime.run$1$gowrapper
           9:  0xdc1 - <unknown>!tinygo_launch
          10: 0x2ce48 - <unknown>!_start
       note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
    2: wasm trap: wasm `unreachable` instruction executed

@rockwotj
Copy link
Contributor

rockwotj commented Nov 21, 2023

FWIW I have successfully used https://github.com/planetscale/vtprotobuf to marshal/unmarshal protobuf in tinygo -target=wasi

(this can be closed then?)

@wrnlb666
Copy link

wrnlb666 commented Apr 8, 2024

How are you able to use vtprotobuf with tinygo? Isn't the generated code from vtprotobuf depends on the result of protobuf-go? I am still getting the same error with my _vtproto.pb.go file.

@rockwotj
Copy link
Contributor

rockwotj commented Apr 8, 2024

How are you able to use vtprotobuf with tinygo? Isn't the generated code from vtprotobuf depends on the result of protobuf-go?

The reflection methods are stubbed out, so it still compiles and the vtprotobuf version doesn't invoke the reflection methods, so it works fine for me.

I am still getting the same error with my _vtproto.pb.go file.

Post the error and make sure you're on the latest tinygo version

@wrnlb666
Copy link

wrnlb666 commented Apr 9, 2024

I am on the latest tinygo v0.31.1, and I am also using it with wasmtime. The error I got is exactly the same with the one you posted before without using vtprotobuf. Did you change any of the code generated by protoc --go_out ?

@rockwotj
Copy link
Contributor

rockwotj commented Apr 9, 2024

no modifications needed. Can you post a reproduction?

@wrnlb666
Copy link

wrnlb666 commented Apr 9, 2024

I am so sorry to bother u, it was me making a dumb mistake causing the error, I fixed the error and it works totally fine. Thank you so much.

@paralin
Copy link
Contributor

paralin commented Apr 10, 2024

vtprotobuf generates static code for Marshal and Unmarshal. We just need a version of protoc-gen-go that does not import reflect nor any of the "heavy" protobuf packages that add a lot of complexity to the resulting binary.

I have forked to protoc-gen-go-lite here and have already dropped everything but the protoc plugin, and am working on adjusting the compiler to generate bare structs without referencing reflect: aperturerobotics/protobuf-go-lite#1

Please join the effort there as this is intended to make it easier to build lightweight tinygo protobuf projects.

paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 10, 2024
vtprotobuf generates static code for Marshal and Unmarshal. We just need a
version of protoc-gen-go that does not import reflect nor any of the "heavy"
protobuf packages that add a lot of complexity to the resulting binary.

tinygo-org/tinygo#2667

Drop all unused code and fix linter warnings.

Signed-off-by: Christian Stewart <christian@aperture.us>
paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 10, 2024
vtprotobuf generates static code for Marshal and Unmarshal. We just need a
version of protoc-gen-go that does not import reflect nor any of the "heavy"
protobuf packages that add a lot of complexity to the resulting binary.

tinygo-org/tinygo#2667

Drop all unused code and fix linter warnings.

Signed-off-by: Christian Stewart <christian@aperture.us>
paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 11, 2024
vtprotobuf generates static code for Marshal and Unmarshal. We just need a
version of protoc-gen-go that does not import reflect nor any of the "heavy"
protobuf packages that add a lot of complexity to the resulting binary.

tinygo-org/tinygo#2667

Drop all unused code and fix linter warnings.

Drop protoimpl.EnforceVersion lines

Add link to vtprotobuf-lite

Drop weak fields, extensions, json marshal, errors pkg.

Signed-off-by: Christian Stewart <christian@aperture.us>
paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 11, 2024
vtprotobuf generates static code for Marshal and Unmarshal. We just need a
version of protoc-gen-go that does not import reflect nor any of the "heavy"
protobuf packages that add a lot of complexity to the resulting binary.

tinygo-org/tinygo#2667

Drop all unused code and fix linter warnings.

Drop protoimpl.EnforceVersion lines

Add link to vtprotobuf-lite

Drop weak fields, extensions, json marshal, errors pkg.

Drop testprotos.

Signed-off-by: Christian Stewart <christian@aperture.us>
paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 11, 2024
vtprotobuf generates static code for Marshal and Unmarshal. We just need a
version of protoc-gen-go that does not import reflect nor any of the "heavy"
protobuf packages that add a lot of complexity to the resulting binary.

tinygo-org/tinygo#2667

Drop all unused code and fix linter warnings.

Drop protoimpl.EnforceVersion lines

Add link to vtprotobuf-lite

Drop weak fields, extensions, json marshal, errors pkg.

Drop testprotos.

Signed-off-by: Christian Stewart <christian@aperture.us>
paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 11, 2024
vtprotobuf generates static code for Marshal and Unmarshal. We just need a
version of protoc-gen-go that does not import reflect nor any of the "heavy"
protobuf packages that add a lot of complexity to the resulting binary.

tinygo-org/tinygo#2667

Drop all unused code and fix linter warnings.

Drop protoimpl.EnforceVersion lines

Add link to vtprotobuf-lite

Drop weak fields, extensions, json marshal, errors pkg.

Drop testprotos.

Hand-write String() for timestamp and duration.

Signed-off-by: Christian Stewart <christian@aperture.us>
@paralin
Copy link
Contributor

paralin commented Apr 11, 2024

I have completed protobuf-go-lite which is a reflection-free fork of protobuf-go merged with vtprotobuf and protoc-gen-go-json.

Library: https://github.com/aperturerobotics/protobuf-go-lite
Example: https://github.com/aperturerobotics/protobuf-project/tree/protobuf-lite

RPCs are available as well with starpc: https://github.com/aperturerobotics/starpc

protobuf-go-lite now supports reflection-free protobuf and protojson encoding!

paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 12, 2024
This is a version of protobuf-go that does not use reflection.

Reflection adds weight to the compiled binary and is not supported fully by
tinygo. We can eliminate the requirement on reflect with vtprotobuf, which
generates static code for Marshal and Unmarshal.

tinygo-org/tinygo#2667

This commit merges vtprotobuf and protobuf-go-lite into a single repo.
This allows tightly integrating the protobuf-go compiler and the vtprotobuf
compiler, generating a single .pb.go file instead of multiple files. This also
allows radical simplifications of the protobuf compiler plugin and the generated
vtprotobuf code, eliminating the need for extra wrapper code.

Major changes from upstream:

- Drop all unused code and fix linter warnings.
- Drop pooling
- Add link to protobuf-go-lite
- Drop grpc
- Drop exts
- Drop references to ProtoPkg
- Dropped pool from vtprotobuf
- Dropped MessageSet (deprecated)
- Dropped any (requires reflect)
- Dropped fieldmask (requires reflect)
- Dropped the -wrap option for vtprotobuf
- Allow import paths without slashes in protogen
- Derive Go package name from the proto3 package name
- Derive Go import path from the proto3 adjacency to Go packages
- Generate a String() for enums which does not use reflect

Signed-off-by: Christian Stewart <christian@aperture.us>
paralin added a commit to aperturerobotics/starpc that referenced this issue Apr 15, 2024
This is a reflection-less version of protobuf-go with vtprotobuf.

Now starpc works without the reflect package, which is much better for
supporting platforms like WebAssembly and tinygo, where every import matters in
terms of managing binary size, and the reflection support may be limited.

Reflection adds weight to the compiled binary and is not supported fully by
tinygo. We can eliminate the requirement on reflect with vtprotobuf, which
generates static code for Marshal and Unmarshal.

See: tinygo-org/tinygo#2667
See: aperturerobotics/protobuf-go-lite@e0016a1

Signed-off-by: Christian Stewart <christian@aperture.us>
paralin added a commit to aperturerobotics/protobuf-go-lite that referenced this issue Apr 20, 2024
This commit implements protojson support by merging in a fork of:

https://github.com/TheThingsIndustries/protoc-gen-go-json

protoc-gen-go-json has been heavily modified to integrate cleanly with
vtprotobuf and the rest of protobuf-go-lite.

Currently proto2 and proto3opt are not supported w/ the json feature.

This implements reflection-free protojson support for tinygo:

tinygo-org/tinygo#2667 (comment)

Signed-off-by: Christian Stewart <christian@aperture.us>
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

7 participants