commit 8bc8707323078cfe8b83dd28f876aedf7a234f37
parent b0f9d289cb2739b2aea041d8ec614f791748c593
Author: francoispqt <francois@parquet.ninja>
Date: Sun, 20 May 2018 20:16:36 +0800
add http-benchmarks example
Diffstat:
5 files changed, 478 insertions(+), 0 deletions(-)
diff --git a/examples/http-benchmarks/Makefile b/examples/http-benchmarks/Makefile
@@ -0,0 +1,4 @@
+
+.PHONY: bench
+bench:
+ wrk -d 20s -s post.lua http://localhost:3000
+\ No newline at end of file
diff --git a/examples/http-benchmarks/README.md b/examples/http-benchmarks/README.md
@@ -0,0 +1,52 @@
+# HTTP BENCHMARKS
+
+This package has two different implementation of a basic HTTP server in Go. It just takes a JSON body, unmarshals it and marshals it back to the response.
+
+It required `wrk` benchmarking tool, which you can find here: https://github.com/wg/wrk
+
+## How to run
+
+### gojay
+```bash
+cd /path/to/package && go run gojay/main.go
+```
+Then run:
+```bash
+cd /path/to/package && make bench
+```
+
+### standard package (encoding/json)
+```bash
+cd /path/to/package && go run standard/main.go
+```
+Then run:
+```bash
+cd /path/to/package && make bench
+```
+
+## Results
+
+Results presented here are ran on a MacBook Pro Mid 2015 2,2 GHz Intel Core i7 with 16G of RAM
+
+**gojay results:**
+```
+Running 20s test @ http://localhost:3000
+ 2 threads and 10 connections
+ Thread Stats Avg Stdev Max +/- Stdev
+ Latency 298.77us 341.40us 10.52ms 94.13%
+ Req/Sec 18.88k 1.89k 21.40k 73.63%
+ 755246 requests in 20.10s, 1.67GB read
+Requests/sec: 37573.84
+Transfer/sec: 84.85MB
+```
+**standard results:**
+```
+Running 20s test @ http://localhost:3000
+ 2 threads and 10 connections
+ Thread Stats Avg Stdev Max +/- Stdev
+ Latency 613.21us 557.50us 12.65ms 93.88%
+ Req/Sec 9.18k 423.20 10.10k 80.50%
+ 365404 requests in 20.00s, 811.60MB read
+Requests/sec: 18269.66
+Transfer/sec: 40.58MB
+```
+\ No newline at end of file
diff --git a/examples/http-benchmarks/gojay/main.go b/examples/http-benchmarks/gojay/main.go
@@ -0,0 +1,158 @@
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/francoispqt/gojay"
+)
+
+func main() {
+ log.Println("Listening on port 3000")
+ log.Fatal(http.ListenAndServe(":3000", http.HandlerFunc(handler)))
+}
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ var body Body
+ dec := gojay.BorrowDecoder(r.Body)
+ defer dec.Release()
+ err := dec.Decode(&body)
+ if err != nil {
+ panic(err)
+ }
+ w.Header().Set("Content-Type", "application/json")
+ enc := gojay.BorrowEncoder(w)
+ defer enc.Release()
+ err = enc.Encode(&body)
+ if err != nil {
+ panic(err)
+ }
+}
+
+type Body struct {
+ Colors *colors `json:"colors"`
+}
+
+func (c *Body) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+ switch k {
+ case "colors":
+ cols := make(colors, 0)
+ c.Colors = &cols
+ return dec.Array(c.Colors)
+ }
+ return nil
+}
+func (b *Body) NKeys() int {
+ return 1
+}
+
+func (b *Body) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.ArrayKey("colors", b.Colors)
+}
+func (b *Body) IsNil() bool {
+ return b == nil
+}
+
+type colors []*Color
+
+func (b *colors) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ color := &Color{}
+ if err := dec.Object(color); err != nil {
+ return err
+ }
+ *b = append(*b, color)
+ return nil
+}
+
+func (b *colors) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, color := range *b {
+ enc.Object(color)
+ }
+}
+
+func (b *colors) IsNil() bool {
+ return len(*b) == 0
+}
+
+type Color struct {
+ Color string `json:"color,omitempty"`
+ Category string `json:"category,omitempty"`
+ Type string `json:"type,omitempty"`
+ Code *Code `json:"code,omitempty"`
+}
+
+func (b *Color) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+ switch k {
+ case "color":
+ return dec.String(&b.Color)
+ case "category":
+ return dec.String(&b.Category)
+ case "type":
+ return dec.String(&b.Type)
+ case "code":
+ b.Code = &Code{}
+ return dec.Object(b.Code)
+ }
+ return nil
+}
+func (b *Color) NKeys() int {
+ return 4
+}
+
+func (b *Color) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.ObjectKey("code", b.Code)
+ enc.StringKey("color", b.Color)
+ enc.StringKey("category", b.Category)
+ enc.StringKey("type", b.Type)
+}
+func (b *Color) IsNil() bool {
+ return b == nil
+}
+
+type Code struct {
+ RGBA *ints `json:"rgba,omitempty"`
+ Hex string `json:"hex,omitempty"`
+}
+
+func (c *Code) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+ switch k {
+ case "rgba":
+ rgba := make(ints, 0)
+ c.RGBA = &rgba
+ return dec.Array(&rgba)
+ case "hex":
+ return dec.String(&c.Hex)
+ }
+ return nil
+}
+func (b *Code) NKeys() int {
+ return 2
+}
+
+func (b *Code) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.ArrayKey("rgba", b.RGBA)
+ enc.StringKey("hex", b.Hex)
+}
+func (b *Code) IsNil() bool {
+ return b == nil
+}
+
+type ints []int
+
+func (v *ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var i int
+ if err := dec.Int(&i); err != nil {
+ return err
+ }
+ *v = append(*v, i)
+ return nil
+}
+
+func (v *ints) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, i := range *v {
+ enc.Int(i)
+ }
+}
+func (v *ints) IsNil() bool {
+ return v == nil || len(*v) == 0
+}
diff --git a/examples/http-benchmarks/post.lua b/examples/http-benchmarks/post.lua
@@ -0,0 +1,220 @@
+wrk.method = "POST"
+wrk.body = [=[
+ {
+ "colors": [
+ {
+ "color": "black",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,255,1],
+ "hex": "#000"
+ }
+ },
+ {
+ "color": "white",
+ "category": "value",
+ "code": {
+ "rgba": [0,0,0,1],
+ "hex": "#FFF"
+ }
+ },
+ {
+ "color": "red",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,0,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "blue",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [0,0,255,1],
+ "hex": "#00F"
+ }
+ },
+ {
+ "color": "yellow",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "green",
+ "category": "hue",
+ "type": "secondary",
+ "code": {
+ "rgba": [0,255,0,1],
+ "hex": "#0F0"
+ }
+ },
+ {
+ "color": "black",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,255,1],
+ "hex": "#000"
+ }
+ },
+ {
+ "color": "white",
+ "category": "value",
+ "code": {
+ "rgba": [0,0,0,1],
+ "hex": "#FFF"
+ }
+ },
+ {
+ "color": "red",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,0,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "blue",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [0,0,255,1],
+ "hex": "#00F"
+ }
+ },
+ {
+ "color": "yellow",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "green",
+ "category": "hue",
+ "type": "secondary",
+ "code": {
+ "rgba": [0,255,0,1],
+ "hex": "#0F0"
+ }
+ },
+ {
+ "color": "black",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,255,1],
+ "hex": "#000"
+ }
+ },
+ {
+ "color": "white",
+ "category": "value",
+ "code": {
+ "rgba": [0,0,0,1],
+ "hex": "#FFF"
+ }
+ },
+ {
+ "color": "red",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,0,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "blue",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [0,0,255,1],
+ "hex": "#00F"
+ }
+ },
+ {
+ "color": "yellow",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "green",
+ "category": "hue",
+ "type": "secondary",
+ "code": {
+ "rgba": [0,255,0,1],
+ "hex": "#0F0"
+ }
+ },
+ {
+ "color": "black",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,255,1],
+ "hex": "#000"
+ }
+ },
+ {
+ "color": "white",
+ "category": "value",
+ "code": {
+ "rgba": [0,0,0,1],
+ "hex": "#FFF"
+ }
+ },
+ {
+ "color": "red",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,0,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "blue",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [0,0,255,1],
+ "hex": "#00F"
+ }
+ },
+ {
+ "color": "yellow",
+ "category": "hue",
+ "type": "primary",
+ "code": {
+ "rgba": [255,255,0,1],
+ "hex": "#FF0"
+ }
+ },
+ {
+ "color": "green",
+ "category": "hue",
+ "type": "secondary",
+ "code": {
+ "rgba": [0,255,0,1],
+ "hex": "#0F0"
+ }
+ }
+ ]
+ }
+]=]
+wrk.headers["Content-Type"] = "application/json"
diff --git a/examples/http-benchmarks/standard/main.go b/examples/http-benchmarks/standard/main.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "encoding/json"
+ "log"
+ "net/http"
+)
+
+func main() {
+ log.Println("Listening on port 3000")
+ log.Fatal(http.ListenAndServe(":3000", http.HandlerFunc(handler)))
+}
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ var body Body
+ err := json.NewDecoder(r.Body).Decode(&body)
+ if err != nil {
+ panic(err)
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ err = json.NewEncoder(w).Encode(body)
+ if err != nil {
+ panic(err)
+ }
+}
+
+type Body struct {
+ Colors []Color `json:"colors"`
+}
+
+type Color struct {
+ Color string `json:"color,omitempty"`
+ Category string `json:"category,omitempty"`
+ Type string `json:"type,omitempty"`
+ Code Code `json:"code,omitempty"`
+}
+
+type Code struct {
+ RGBA []int `json:"rgba,omitempty"`
+ Hex string `json:"hex,omitempty"`
+}