Giter Club home page Giter Club logo

fastpb's Introduction

Fastpb

A faster Protobuf serializer & deserializer.

Attention

  • only proto3 is supported now.
  • known-types(any, api, duration...) is not supported now.

Install

go install github.com/cloudwego/fastpb/protoc-gen-fastpb@latest

Usage

Refer to examples, use in two steps:

  1. use fastpb to generate code. (refer here)
  2. use fastpb API to marshal/unmarshal. (refer here)

Step 1: Generate Code

Using the command line tool to generate code:

protoc --go_out=. \
  --fastpb_out=. \
  ${your_idl}.proto

or

protoc --go_opt=paths=source_relative --go_out=. \
  --fastpb_opt=paths=source_relative --fastpb_out=. \
   ${your_idl}.proto

Step 2: Codec Message

Encoding and Decoding must use fastpb's API, shown as demo:

package examples

import (
	"github.com/cloudwego/fastpb"
)

// Marshal .
func Marshal(msg fastpb.Writer) []byte {
	// TODO: buffer can be reused.
	buf := make([]byte, msg.Size())

	msg.FastWrite(buf)
	return buf
}

// Unmarshal .
func Unmarshal(buf []byte, msg fastpb.Reader) error {
	_, err := fastpb.ReadMessage(buf, int8(fastpb.SkipTypeCheck), msg)
	return err
}

Performance

goos: linux
goarch: amd64
pkg: github.com/cloudwego/fastpb/benchmark
cpu: Intel(R) Xeon(R) Gold 5118 CPU @ 2.30GHz

Benchmarks have compared golang/protobuf (referred to as _golang) and fastpb here.

Marshal

Benchmark_marshal_number_golang-48 375.2 ns/op ~ 96 B/op ~ 1 allocs/op
Benchmark_marshal_number_fastpb-48 145.7 ns/op -61.17% 0 B/op -100.00% 0 allocs/op
Benchmark_marshal_string_golang-48 1010 ns/op ~ 2304 B/op ~ 1 allocs/op
Benchmark_marshal_string_fastpb-48 58.57 ns/op -94.20% 0 B/op -100.00% 0 allocs/op
Benchmark_marshal_list_golang-48 8788 ns/op ~ 18432 B/op ~ 1 allocs/op
Benchmark_marshal_list_fastpb-48 3430 ns/op -60.97% 0 B/op -100.00% 0 allocs/op
Benchmark_marshal_map_golang-48 43497 ns/op ~ 21680 B/op ~ 393 allocs/op
Benchmark_marshal_map_fastpb-48 5951 ns/op -86.32% 0 B/op -100.00% 0 allocs/op

Unmarshal

Benchmark_unmarshal_number_golang-48 497.1 ns/op ~ 144 B/op 1 allocs/op
Benchmark_unmarshal_number_fastpb-48 431.6 ns/op -13.18% 144 B/op 1 allocs/op
Benchmark_unmarshal_string_golang-48 939.7 ns/op ~ 2128 B/op 3 allocs/op
Benchmark_unmarshal_string_fastpb-48 668.4 ns/op -28.87% 2128 B/op 3 allocs/op
Benchmark_unmarshal_list_golang-48 12527 ns/op ~ 20296 B/op 99 allocs/op
Benchmark_unmarshal_list_fastpb-48 12593 ns/op +0.53% 20296 B/op 99 allocs/op
Benchmark_unmarshal_map_golang-48 49868 ns/op ~ 24226 B/op 426 allocs/op
Benchmark_unmarshal_map_fastpb-48 21213 ns/op -57.46% 21467 B/op 61 allocs/op

fastpb's People

Contributors

hchenn avatar heyjavabean avatar ppzqh avatar purewhitewu avatar simon0-o avatar sishui avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastpb's Issues

在fastpb面添加一个marshalTo方法,以便能够进行内存复用

echopb:

syntax = "proto3";
package pbapi;
// The greeting service definition.
option go_package = "./;pbapi";

message Request {
  string message = 1;
}

message Response {
  string message = 1;
}

service Echo {
  rpc Echo (Request) returns (Response) {}
}

编解码echo消息:

func Marshal(msg fastpb.Writer) []byte {
	// TODO: buffer can be reused.
	buf := make([]byte, msg.Size())

	msg.FastWrite(buf)
	return buf
}
func Unmarshal(buf []byte, msg fastpb.Reader) error {
	_, err := fastpb.ReadMessage(buf, int8(fastpb.SkipTypeCheck), msg)
	return err
}

marshalTo方法,能够实现内存复用:

func MarshalTo(bp []byte,msg fastpb.Writer) (n int,err error) {
       if msg.size()> cap(bp){
         ....
       }
	msg.FastWrite(buf)
	return ...
}

custom go_package name, error

Describe the bug

When the go_package name is customized, the generated pb.fast.go is wrong

Steps to reproduce the behavior:
custom go_package:

option go_package = "github.com/cloudwego/fastpb/examples/fastpb_gen/user/player;playercustom";

although the official documentation does not recommend this, but it is legal.

Sizer 与业务字段冲突

当proto定义种有一个字段命名为size 时会与fastpb生成的 Size() 方法冲突,虽然可以修改size为其他命名绕过,但是size变量这个太常用了,对于后期切换到fastpb的项目来说改字段名是个很困难的事情(需要考虑旧版客户端兼容性)

message TestMsg {
  int32 size = 1;
}

fastpb/fastpb.go

Lines 31 to 33 in 6fc453d

type Sizer interface {
Size() (n int)
}

建议解决方案:将Size加一个前缀比如 FastSize

// Sizer is designed for generating code.
type Sizer interface {
	FastSize() (n int)
}

安装 fastpb 的问题

请问是否遇到过这样的问题:已下载 [email protected] 但提示 does not contain package github.com/cloudwego/fastpb

github.com/cloudwego/fastpb: module github.com/cloudwego/fastpb@latest found (v0.0.4), but does not contain package github.com/cloudwego/fastpb

当idl 有子目录时

Describe the bug

user.protopet.proto 子文件夹中(如 idl/user/user.proto, idl/pet/pet.proto)时出现引用,如pet/pet.proto中引用了user/user.proto, 生成的user.pb.go的 中的 protoreflect.FileDescriptor 变量名会是File_user_user_proto,而pet.fast.pb.go中最后一行生成的却是 var _ = user.File_user_proto,从而导致报错不可用

Failed to compile when using google protobuf files

Describe the bug
cloudwego/kitex#835
When importing google protobuf files, such as timestamp, those structs don't have fastpb interface, so users cannot compile codes.

To Reproduce

syntax = "proto3";
 
option go_package = "pbdemo";
import "google/protobuf/timestamp.proto";

package pbdemo;
 
service ServiceA {
  rpc SayHello (Request) returns (Reply) {}
}
 
message Request {
  string name = 1;
  google.protobuf.Timestamp date = 4;
}
 
message Reply {
  string message = 1;
}

提供grpc的插件来兼容kitex的grpc协议

当前kitex框架时是kitex封装protoc命令的形式来生成grpc的代码。公司当前的grpc框架是用的gogo/protobuf来生成grpc客户端服务端代码。经过测试, 发现fastpb的性能仍然比不上gogo/protobuf,查看对比源码,发现可能是fastpb不够简洁造成的,整体实现原理差不多.

因此,是否可以protoc的形式来生成kitex grpc代码呢:

protoc --fastpb_out=... --fastpb_grpcout=...

而不是使用kitex,因为里面包含了非常多的冗余的东西:

protoc -I . --plugin=protoc-gen-kitex=go\bin\kitex.exe --kitex_out=kitex_gen --kitex_opt="Verbose=true,GenerateMain=true,GenerateInvoker=false,Version=v0.5.2,NoFastAPI=true,ModuleName=example,ServiceName=GoRoomService,Use=,IDLType=protobuf,Includes=.,ThriftOptions=naming_style=golint;ignore_initialisms;gen_setter;gen_deep_equal;compatible_names;frugal_tag,ProtobufOptions=Mecho.proto=example/kitex_gen,IDL=./echo.proto,OutputPath=C:\\project\\example,PackagePrefix=example/kitex_gen,CombineService=false,CopyIDL=false,ProtobufPlugins=gofast::.,Features=,FrugalPretouch=false,ThriftPluginTimeLimit=1m0s,ExtensionFile=,Record=false,RecordCmd=\go\\bin\\kitex.exe;-service;GoRoomService;-module;example;-I;.;-no-fast-api;--protobuf;Mecho.proto=example/kitex_gen;-protobuf-plugin=gofast::.;-v;./echo.proto,TemplateDir=,GenPath=kitex_gen" --kitex_opt=Mecho.proto=example/kitex_gen --gofast_out=. --gofast_opt= ./echo.proto

导入 google protobuf 报错

Describe the bug
Cannot use '&v' (type *wrappers.StringValue) as the type ReaderType does not implement 'Reader' as some methods are missing:FastRead(buf []byte, _type int8, number int32) (n int, err error)

11

Unresolved reference 'File_common_realm_proto'

2022-11-03 11-46-32屏幕截图

To Reproduce
执行了下面命令
kitex -module "gitlab.mvalley.com/fgq/kitex_demo" -service getinfo ./proto/info/kd.proto

Screenshots

本地文件 proto/common_realm/common.proto
2022-11-03 11-28-43屏幕截图
本地文件 proto_vendor/google/protobuf/wrappers.proto
2022-11-03 11-29-13屏幕截图

fastpb version:
Code generated by FastPB v0.0.1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.