-
Notifications
You must be signed in to change notification settings - Fork 414
Closed
Description
Describe the bug
Even after pretouching the marshaled type, the latency of marshaling the type takes time of milliseconds order, which may be risk breaking the SLAs of some endpoints. I am wondering what additional things I can do to avoid this risk.
To Reproduce
Can run the following toy program:
package main
import (
"encoding/xml"
"fmt"
"reflect"
"time"
"github.com/brianvoe/gofakeit/v5"
"github.com/bytedance/sonic"
)
type status struct {
Name string `xml:"name"`
ID int `xml:"id"`
Description string `xml:"description"`
GroupID int `xml:"groupId"`
GroupName string `xml:"groupName"`
Action string `xml:"action"`
}
type message struct {
MessageID string `xml:"messageId"`
To string `xml:"to"`
SmsCount int `xml:"smsCount"`
Status status `xml:"status"`
}
type serviceException struct {
MessageID string `xml:"messageId"`
Text string `xml:"text"`
}
type requestError struct {
ServiceException serviceException `xml:"serviceException"`
}
type infobipResponse struct {
Name xml.Name `xml:"smsResponse"`
Messages []message `xml:"messages>message"`
RequestError requestError `xml:"requestError"`
}
func generateResponse() *infobipResponse {
return &infobipResponse{
Name: xml.Name{Space: gofakeit.URL(), Local: gofakeit.Word()},
Messages: []message{
{
MessageID: gofakeit.UUID(),
To: gofakeit.Phone(),
SmsCount: gofakeit.Number(1, 10),
Status: status{
Name: gofakeit.Word(),
ID: gofakeit.Number(1, 10),
Description: gofakeit.Sentence(10),
GroupID: gofakeit.Number(1, 10),
GroupName: gofakeit.Word(),
Action: gofakeit.Word(),
},
},
},
RequestError: requestError{
ServiceException: serviceException{
MessageID: gofakeit.UUID(),
Text: gofakeit.Sentence(40),
},
},
}
}
func main() {
totalLen := 0 // just to avoid optimization
cnt := 0
t := reflect.TypeOf(generateResponse())
printTime("pre", func() { sonic.Pretouch(t) })
for i := 1; i <= 10; i++ {
payload := generateResponse()
printTime(fmt.Sprintf("run %d", i), func() {
out, _ := sonic.Marshal(payload)
totalLen += len(out)
cnt++
})
}
fmt.Printf("len\t\t%v\n", totalLen/cnt)
}
func printTime(v string, fn func()) {
start := time.Now()
fn()
fmt.Printf("%s\t\t%v\n", v, time.Since(start))
}
Then, the result will look like this:
pre 13.021132ms
run 1 1.053851ms
run 2 1.911µs
run 3 588ns
run 4 559ns
run 5 487ns
run 6 1.799µs
run 7 476ns
run 8 443ns
run 9 501ns
run 10 460ns
len 731
For reference, here is the output if we use encoding/json, where no latency exceed 100 microseconds:
run 1 85.921µs
run 2 2.042µs
run 3 2.013µs
run 4 1.752µs
run 5 2.07µs
run 6 3.215µs
run 7 2.116µs
run 8 1.989µs
run 9 1.231µs
run 10 2.131µs
len 729
Things I have tried on top of pretouching that does not help:
- adding time.Sleep before marshal
- marshaling other types
- creating a value from the pretouched type, i.e.
reflect.New(t.Elem()).Interface()
, and marshaling that
Expected behavior
There is no marshaling latency on miliseconds level, even on the first marshal.
Sonic version:
v1.13.3
Environment:
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/bimoadityar/.cache/go-build"
GOENV="/home/bimoadityar/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/bimoadityar/.go/pkg/mod"
GOOS="linux"
GOPATH="/home/bimoadityar/.go"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/bimoadityar/.config/spkit/bin/sdk/go1.17.13"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/bimoadityar/.config/spkit/bin/sdk/go1.17.13/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17.13"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/bimoadityar/Documents/bimo-test-2/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1204808054=/tmp/go-build -gno-record-gcc-switches"
Metadata
Metadata
Assignees
Labels
No labels