Skip to content

Commit 07fe423

Browse files
authored
Merge pull request #476 from WillAbides/rjson
Rjson benchmarks (go)
2 parents 0fdcdbd + f3441f8 commit 07fe423

File tree

5 files changed

+199
-1
lines changed

5 files changed

+199
-1
lines changed

json/Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ executables := \
6767
target/json_zig \
6868
target/json_yajl_gcc \
6969
target/json_yajl_clang \
70-
target/json_sonic
70+
target/json_sonic \
71+
target/json_rjson \
72+
target/json_rjson_custom
7173

7274
artifacts := $(executables) \
7375
target/test.exe \
@@ -342,6 +344,12 @@ target/json_sonic: test_sonic.go | $(gofmt)
342344
go mod tidy
343345
$(GO_BUILD)
344346

347+
target/json_rjson: test_rjson.go
348+
$(GO_BUILD)
349+
350+
target/json_rjson_custom: test_rjson_custom.go
351+
$(GO_BUILD)
352+
345353
json-fsharp/target/Release/net7.0/json-fsharp: json-fsharp/json-fsharp.fsproj json-fsharp/Program.fs
346354
$(DOTNET_BUILD)
347355

json/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/bytedance/sonic v1.10.1
77
github.com/goccy/go-json v0.10.2
88
github.com/json-iterator/go v1.1.12
9+
github.com/willabides/rjson v0.2.0
910
)
1011

1112
require (

json/go.sum

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,18 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
2929
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
3030
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
3131
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
32+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
3233
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
3334
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
3435
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
3536
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
3637
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
3738
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
3839
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
40+
github.com/willabides/rjson v0.1.0 h1:RsKCjyFqCNjj4P6G8kJcddjLLqeyxYMs9ZiT1uU/ZUA=
41+
github.com/willabides/rjson v0.1.0/go.mod h1:9fWQED96t+VlaF7GPwf/qRHLdNbAjjBkaPxmmjyuW5E=
42+
github.com/willabides/rjson v0.2.0 h1:cgBIzis7l9ugUTtaLMcl12pJBu1m62oTBGf/XXBHhJI=
43+
github.com/willabides/rjson v0.2.0/go.mod h1:9fWQED96t+VlaF7GPwf/qRHLdNbAjjBkaPxmmjyuW5E=
3944
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
4045
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
4146
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

json/test_rjson.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"log"
7+
"net"
8+
"os"
9+
10+
"github.com/willabides/rjson"
11+
)
12+
13+
type Coordinate struct {
14+
X, Y, Z float64
15+
}
16+
17+
type TestStruct struct {
18+
Coordinates []Coordinate
19+
}
20+
21+
func notify(msg string) {
22+
conn, err := net.Dial("tcp", "localhost:9001")
23+
if err == nil {
24+
fmt.Fprintf(conn, msg)
25+
conn.Close()
26+
}
27+
}
28+
29+
func calc(bytes []byte) Coordinate {
30+
jobj := TestStruct{}
31+
32+
var buffer rjson.Buffer
33+
var currentCoord *Coordinate
34+
35+
coordHandler := rjson.ObjectValueHandlerFunc(func(fieldname, data []byte) (int, error) {
36+
switch string(fieldname) {
37+
case "x":
38+
return rjson.DecodeFloat64(data, &currentCoord.X)
39+
case "y":
40+
return rjson.DecodeFloat64(data, &currentCoord.Y)
41+
case "z":
42+
return rjson.DecodeFloat64(data, &currentCoord.Z)
43+
}
44+
return rjson.SkipValueFast(data, &buffer)
45+
})
46+
47+
coordsHandler := rjson.ArrayValueHandlerFunc(func(data []byte) (int, error) {
48+
jobj.Coordinates = append(jobj.Coordinates, Coordinate{})
49+
currentCoord = &jobj.Coordinates[len(jobj.Coordinates)-1]
50+
return rjson.HandleObjectValues(data, coordHandler, &buffer)
51+
})
52+
53+
rjson.HandleObjectValues(bytes, rjson.ObjectValueHandlerFunc(func(fieldname, data []byte) (int, error) {
54+
if string(fieldname) != "coordinates" {
55+
return rjson.SkipValueFast(data, &buffer)
56+
}
57+
return rjson.HandleArrayValues(data, coordsHandler, &buffer)
58+
}), &buffer)
59+
60+
x, y, z := 0.0, 0.0, 0.0
61+
62+
for _, coord := range jobj.Coordinates {
63+
x += coord.X
64+
y += coord.Y
65+
z += coord.Z
66+
}
67+
68+
len := float64(len(jobj.Coordinates))
69+
return Coordinate{x / len, y / len, z / len}
70+
}
71+
72+
func main() {
73+
right := Coordinate{2.0, 0.5, 0.25}
74+
for _, v := range []string{
75+
`{"coordinates":[{"x":2.0,"y":0.5,"z":0.25}]}`,
76+
`{"coordinates":[{"y":0.5,"x":2.0,"z":0.25}]}`} {
77+
left := calc([]byte(v))
78+
if left != right {
79+
log.Fatalf("%+v != %+v\n", left, right)
80+
}
81+
}
82+
83+
bytes, err := ioutil.ReadFile("/tmp/1.json")
84+
if err != nil {
85+
panic(fmt.Sprintf("%v", err))
86+
}
87+
88+
notify(fmt.Sprintf("Go (rjson)\t%d", os.Getpid()))
89+
results := calc(bytes)
90+
notify("stop")
91+
92+
fmt.Printf("%+v\n", results)
93+
}

json/test_rjson_custom.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"log"
7+
"net"
8+
"os"
9+
10+
"github.com/willabides/rjson"
11+
)
12+
13+
type Coordinate struct {
14+
X, Y, Z float64
15+
}
16+
17+
func notify(msg string) {
18+
conn, err := net.Dial("tcp", "localhost:9001")
19+
if err == nil {
20+
fmt.Fprintf(conn, msg)
21+
conn.Close()
22+
}
23+
}
24+
25+
type handler struct {
26+
buffer rjson.Buffer
27+
coord Coordinate
28+
count float64 // used to calculate the running average
29+
}
30+
31+
func (h *handler) HandleArrayValue(data []byte) (p int, err error) {
32+
h.count++
33+
return rjson.HandleObjectValues(data, h, &h.buffer)
34+
}
35+
36+
// HandleObjectValue handles both the top level object where we only care about the "coordinates" field
37+
// and the object inside the array where we keep a running average of x, y, and z values.
38+
func (h *handler) HandleObjectValue(fieldname, data []byte) (int, error) {
39+
var ptr *float64 // points to X, Y or Z depending on the fieldname
40+
switch string(fieldname) {
41+
case "x":
42+
ptr = &h.coord.X
43+
case "y":
44+
ptr = &h.coord.Y
45+
case "z":
46+
ptr = &h.coord.Z
47+
case "coordinates":
48+
return rjson.HandleArrayValues(data, h, &h.buffer)
49+
default:
50+
return rjson.SkipValueFast(data, &h.buffer)
51+
}
52+
val, p, err := rjson.ReadFloat64(data)
53+
if err != nil {
54+
return p, err
55+
}
56+
*ptr += val
57+
return p, nil
58+
}
59+
60+
func calc(bytes []byte) Coordinate {
61+
h := &handler{}
62+
rjson.HandleObjectValues(bytes, h, &h.buffer)
63+
return Coordinate{
64+
X: h.coord.X / h.count,
65+
Y: h.coord.Y / h.count,
66+
Z: h.coord.Z / h.count,
67+
}
68+
}
69+
70+
func main() {
71+
right := Coordinate{2.0, 0.5, 0.25}
72+
for _, v := range []string{
73+
`{"coordinates":[{"x":2.0,"y":0.5,"z":0.25}]}`,
74+
`{"coordinates":[{"y":0.5,"x":2.0,"z":0.25}]}`} {
75+
left := calc([]byte(v))
76+
if left != right {
77+
log.Fatalf("%+v != %+v\n", left, right)
78+
}
79+
}
80+
81+
bytes, err := ioutil.ReadFile("/tmp/1.json")
82+
if err != nil {
83+
panic(fmt.Sprintf("%v", err))
84+
}
85+
86+
notify(fmt.Sprintf("Go (rjson custom)\t%d", os.Getpid()))
87+
results := calc(bytes)
88+
notify("stop")
89+
90+
fmt.Printf("%+v\n", results)
91+
}

0 commit comments

Comments
 (0)