• Stars
    star
    112
  • Rank 312,240 (Top 7 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 3 years ago
  • Updated 13 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A very fast dynamic Thrift serializer & deserializer.

Frugal

English | 中文

A very fast dynamic Thrift serializer & deserializer based on just-in-time compilation.

Features

Code Generation Free

Traditional Thrift serializer and deserializer are based on generated code which is no longer needed since we can use JIT compilation to dynamically generate machine code.

High Performance

Thanks to JIT compilation, Frugal can generate better machine code than Go language compiler. In multi-core scenarios, Frugal's performance is about 5 times higher than that of traditional serializer and deserializer.

name                                 old time/op    new time/op     delta
MarshalAllSize_Parallel/small-16       78.8ns ± 0%     14.9ns ± 0%    -81.10%
MarshalAllSize_Parallel/medium-16      1.34µs ± 0%     0.32µs ± 0%    -76.32%
MarshalAllSize_Parallel/large-16       37.7µs ± 0%      9.4µs ± 0%    -75.02%
UnmarshalAllSize_Parallel/small-16      368ns ± 0%       30ns ± 0%    -91.90%
UnmarshalAllSize_Parallel/medium-16    11.9µs ± 0%      0.8µs ± 0%    -92.98%
UnmarshalAllSize_Parallel/large-16      233µs ± 0%       21µs ± 0%    -90.99%

name                                 old speed      new speed       delta
MarshalAllSize_Parallel/small-16     7.31GB/s ± 0%  38.65GB/s ± 0%   +428.84%
MarshalAllSize_Parallel/medium-16    12.9GB/s ± 0%   54.7GB/s ± 0%   +322.10%
MarshalAllSize_Parallel/large-16     11.7GB/s ± 0%   46.8GB/s ± 0%   +300.26%
UnmarshalAllSize_Parallel/small-16   1.56GB/s ± 0%  19.31GB/s ± 0%  +1134.41%
UnmarshalAllSize_Parallel/medium-16  1.46GB/s ± 0%  20.80GB/s ± 0%  +1324.55%
UnmarshalAllSize_Parallel/large-16   1.89GB/s ± 0%  20.98GB/s ± 0%  +1009.73%

name                                 old alloc/op   new alloc/op    delta
MarshalAllSize_Parallel/small-16         112B ± 0%         0B        -100.00%
MarshalAllSize_Parallel/medium-16        112B ± 0%         0B        -100.00%
MarshalAllSize_Parallel/large-16         779B ± 0%        57B ± 0%    -92.68%
UnmarshalAllSize_Parallel/small-16     1.31kB ± 0%     0.10kB ± 0%    -92.76%
UnmarshalAllSize_Parallel/medium-16      448B ± 0%      3022B ± 0%   +574.55%
UnmarshalAllSize_Parallel/large-16     1.13MB ± 0%     0.07MB ± 0%    -93.54%

name                                 old allocs/op  new allocs/op   delta
MarshalAllSize_Parallel/small-16         1.00 ± 0%       0.00        -100.00%
MarshalAllSize_Parallel/medium-16        1.00 ± 0%       0.00        -100.00%
MarshalAllSize_Parallel/large-16         1.00 ± 0%       0.00        -100.00%
UnmarshalAllSize_Parallel/small-16       6.00 ± 0%       1.00 ± 0%    -83.33%
UnmarshalAllSize_Parallel/medium-16      6.00 ± 0%      30.00 ± 0%   +400.00%
UnmarshalAllSize_Parallel/large-16      4.80k ± 0%      0.76k ± 0%    -84.10%

What can you do with Frugal ?

Use Frugal as Kitex serializer and deserializer

No more massive serialization and deserialization code, leads to a more tidy project. No more meaningless diff of generated code in code review.

Serialized and Deserialize struct generated by Thriftgo

If you have a Thrift file, and all you need is using Frugal to do serialization and deserialization. You can use thriftgo to generate Go struct, then you can use Frugal.

Serialization and deserialization on a customized Go struct

If you don't want any Thrift files, and you want serialize or deserialize a customized Go struct. You can add some struct field tag to the Go struct, then you can use Frugal.

Usage

Using with Kitex

1. Update Kitex to v0.4.2 or higher version

go get github.com/cloudwego/kitex@latest

2. Generate code with -thrift frugal_tag option

Example:

kitex -thrift frugal_tag -service a.b.c my.thrift

If you don't need codec code, you can use -thrift template=slim option.

kitex -thrift frugal_tag,template=slim -service a.b.c my.thrift

3. Init clients and servers with WithPayloadCodec(thrift.NewThriftFrugalCodec()) option

Client example:

package client

import (
    "context"

    "example.com/kitex_test/client/kitex_gen/a/b/c/echo"
    "github.com/cloudwego/kitex/client"
    "github.com/cloudwego/kitex/pkg/remote/codec/thrift"
)

func Echo() {
    code := thrift.NewThriftCodecWithConfig(thrift.FastRead | thrift.FastWrite | thrift.FrugalRead | thrift.FrugalWrite)
    cli := echo.MustNewClient("a.b.c", client.WithPayloadCodec(codec))
    ...
}

Server example:

package main

import (
    "log"

    "github.com/cloudwego/kitex/server"
    c "example.com/kitex_test/kitex_gen/a/b/c/echo"
    "github.com/cloudwego/kitex/pkg/remote/codec/thrift"
)

func main() {
    code := thrift.NewThriftCodecWithConfig(thrift.FastRead | thrift.FastWrite | thrift.FrugalRead | thrift.FrugalWrite)
    svr := c.NewServer(new(EchoImpl), server.WithPayloadCodec(code))

    err := svr.Run()
    if err != nil {
        log.Println(err.Error())
    }
}

Using with Thrift IDL

Prepare Thrift file

We can define a struct in Thrift file like below:

my.thrift:

struct MyStruct {
    1: string msg
    2: i64 code
}

Use Thriftgo to generate code

Now we have thrift file, we can use Thriftgo with frugal_tag option to generate Go code.

Example:

thriftgo -r -o thrift -g go:frugal_tag,package_prefix=example.com/kitex_test/thrift my.thrift

If you don't need codec code, you can use template=slim option

thriftgo -r -o thrift -g go:frugal_tag,template=slim,package_prefix=example.com/kitex_test/thrift my.thrift

Use Frugal to serialize or deserialize

Now we can use Frugal to serialize or deserialize the struct defined in thrift file.

Example:

package main

import (
    "github.com/cloudwego/frugal"

    "example.com/kitex_test/thrift"
)

func main() {
    ms := &thrift.MyStruct{
        Msg: "my message",
        Code: 1024,
    }
    ...
    buf := make([]byte, frugal.EncodedSize(ms))
    frugal.EncodeObject(buf, nil, ms)
    ...
    got := &thrift.MyStruct{}
    frugal.DecodeObject(buf, got)
    ...
}

Serialization and deserialization on a customized Go struct

Define a Go struct

We can define a struct like this:

type MyStruct struct {
    Msg     string
    Code    int64
    Numbers []int64 
}

Add Frugal tag to struct fields

Frugal tag is like frugal:"1,default,string", 1 is field ID, default is field requiredness, string is field type. Field ID and requiredness is always required, but field type is only required for list, set and enum.

You can add Frugal tag to MyStruct like below:

type MyStruct struct {
    Msg     string  `frugal:"1,default"`
    Code    int64   `frugal:"2,default"`
    Numbers []int64 `frugal:"3,default,list<i64>"`
}

All types example:

type MyEnum int64

type Example struct {
 MyOptBool         *bool            `frugal:"1,optional"`
 MyReqBool         bool             `frugal:"2,required"`
 MyOptByte         *int8            `frugal:"3,optional"`
 MyReqByte         int8             `frugal:"4,required"`
 MyOptI16          *int16           `frugal:"5,optional"`
 MyReqI16          int16            `frugal:"6,required"`
 MyOptI32          *int32           `frugal:"7,optional"`
 MyReqI32          int32            `frugal:"8,required"`
 MyOptI64          *int64           `frugal:"9,optional"`
 MyReqI64          int64            `frugal:"10,required"`
 MyOptString       *string          `frugal:"11,optional"`
 MyReqString       string           `frugal:"12,required"`
 MyOptBinary       []byte           `frugal:"13,optional"`
 MyReqBinary       []byte           `frugal:"14,required"`
 MyOptI64Set       []int64          `frugal:"15,optional,set<i64>"`
 MyReqI64Set       []int64          `frugal:"16,required,set<i64>"`
 MyOptI64List      []int64          `frugal:"17,optional,list<i64>"`
 MyReqI64List      []int64          `frugal:"18,required,list<i64>"`
 MyOptI64StringMap map[int64]string `frugal:"19,optional"`
 MyReqI64StringMap map[int64]string `frugal:"20,required"`
 MyOptEnum         *MyEnum          `frugal:"21,optional,i64"`
 MyReqEnum         *MyEnum          `frugal:"22,optional,i64"`
}

Use Frugal to serialize or deserialize

Example:

package main

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

func main() {
    ms := &thrift.MyStruct{
        Msg: "my message",
        Code: 1024,
        Numbers: []int64{0, 1, 2, 3, 4},
    }
    ...
    buf := make([]byte, frugal.EncodedSize(ms))
    frugal.EncodeObject(buf, nil, ms)
    ...
    got := &thrift.MyStruct{}
    frugal.DecodeObject(buf, got)
    ...
}

More Repositories

1

kitex

Go RPC framework with high-performance and strong-extensibility for building micro-services.
Go
6,844
star
2

netpoll

A high-performance non-blocking I/O networking framework, which focused on RPC scenarios, developed by ByteDance.
Go
2,325
star
3

volo

Rust RPC framework with high-performance and strong-extensibility for building micro-services.
Rust
2,176
star
4

hertz

A high-performance and strong-extensibility Go HTTP framework that helps developers build microservices.
Go
1,161
star
5

goref

Go heap object reference analysis tool
Go
541
star
6

sonic-rs

A fast Rust JSON library based on SIMD.
Rust
379
star
7

shmipc-go

A high performance inter-process communication golang library developed by CloudWeGo
Go
348
star
8

biz-demo

Business Demo for CloudWeGo
Go
146
star
9

dynamicgo

Dynamically and efficiently operate RPC data for Go
Go
141
star
10

pilota

A thrift and protobuf implementation in pure rust with high performance and extensibility.
Rust
120
star
11

cwgo

An all-in-one code generation tool for CloudWeGo
Go
102
star
12

thriftgo

An implementation of thrift compiler in go language.
Go
99
star
13

cloudwego.github.io

Website for CloudWeGo
JavaScript
59
star
14

kitex-examples

Go
50
star
15

netpoll-http2

Go
43
star
16

kitex-benchmark

Go
31
star
17

netpoll-benchmark

Go
18
star
18

hertz-examples

Examples for Hertz.
Go
18
star
19

localsession

transparently transmit context within or between goroutines
Go
18
star
20

configmanager

Go
10
star
21

kitex-tests

Tests for cloudwego/kitex
Go
2
star
22

netpoll-examples

Go
2
star
23

thrift-gen-validator

thrift-gen-validator is a thriftgo plugin to generate struct validators.
Go
2
star
24

.github

1
star
25

community

Governance and community material for CloudWeGo and its open source sub-projects
1
star
26

gopkg

Go
1
star