Skip to content

Commit

Permalink
Merge pull request #165 from deneonet/master
Browse files Browse the repository at this point in the history
Converted root package to main package
  • Loading branch information
deneonet authored Jun 21, 2024
2 parents d9b874e + 32a7ca9 commit 702bb70
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
with:
go-version: ${{ matrix.go }}
- name: Verify benchmarks validate
run: VALIDATE=1 go test -v -bench . -run bench -benchtime 1ms
run: go test -v -bench . -run bench -benchtime 1ms --validate
18 changes: 8 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,25 @@ https://alecthomas.github.io/go_serialization_benchmarks

## Running the benchmarks

To benchmark and validate, without cloning the repository, replace the `.` from the commands below with `github.com/alecthomas/go_serialization_benchmarks@latest`.

```bash
go test -bench=.
go run .
```

To validate the correctness of the serializers:

```bash
VALIDATE=1 go test -bench=. -benchtime=1ms
go run . --validate
```

To update the benchmark report:

```bash
go test -tags genreport -run TestGenerateReport
go run . --genreport
```

To update the benchmark report with using a longer run benchmark (to get more
accurate results):

To update the benchmark report with a longer benchmark run (to get more accurate results):
```bash
go test -tags genreport -run TestGenerateReport -benchtime 10s -timeout 1h
go test -tags genreport -run TestGenerateReport -benchtime 10s -timeout 1h #--validate
```

## Recommendation
Expand Down Expand Up @@ -61,7 +59,7 @@ serializer:
- Regenerate the report by running:

```
go test -tags genreport -run TestGenerateReport
go run . --genreport
```

- **Include the updated report data in your PR**
Expand Down
101 changes: 101 additions & 0 deletions benchmark.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// This file is used to generate the report and is ignored by default on tests.

package main

import (
"encoding/json"
"fmt"
"os"
"strings"
"testing"

"github.com/alecthomas/go_serialization_benchmarks/goserbench"
)

type reportLine struct {
Name string `json:"name"`
MarshalIterCount int `json:"marshal_iter_count"`
UnmarshalIterCount int `json:"unmarshal_iter_count"`
TotalIterCount int `json:"total_iter_count"`
UnsafeStringUnmarshal bool `json:"unsafe_string_unmarshal"`
BufferReuseMarshal bool `json:"buffer_reuse_marshal"`
MarshalNsOp int64 `json:"marshal_ns_op"`
UnmarshalNsOp int64 `json:"unmarshal_ns_op"`
TotalNsOp int64 `json:"total_ns_op"`
SerializationSize int64 `json:"serialization_size"`
MarshalAllocBytes int64 `json:"marshal_alloc_bytes"`
UnmarshalAllocBytes int64 `json:"unmarshal_alloc_bytes"`
TotalAllocBytes int64 `json:"total_alloc_bytes"`
MarshalAllocs int64 `json:"marshal_allocs"`
UnmarshalAllocs int64 `json:"unmarshal_allocs"`
TotalAllocs int64 `json:"total_allocs"`
TimeSupport string `json:"time_support"`
APIKind string `json:"api_kind"`
URL string `json:"url"`
Notes string `json:"notes"`
}

func BenchAndReportSerializers(generateReport bool, validate bool) error {
data := make([]reportLine, len(benchmarkCases))
for i, bench := range benchmarkCases {
marshalRes := testing.Benchmark(func(b *testing.B) {
goserbench.BenchMarshalSmallStruct(b, bench.New())
})
fmt.Printf("%10s - Marshal - %s %s\n", bench.Name, marshalRes.String(),
marshalRes.MemString())
unmarshalRes := testing.Benchmark(func(b *testing.B) {
goserbench.BenchUnmarshalSmallStruct(b, bench.New(), validate)
})
fmt.Printf("%10s - Unmarshal - %s %s\n", bench.Name, unmarshalRes.String(),
unmarshalRes.MemString())

data[i] = reportLine{
Name: bench.Name,
MarshalIterCount: marshalRes.N,
UnmarshalIterCount: unmarshalRes.N,
TotalIterCount: marshalRes.N + unmarshalRes.N,
MarshalNsOp: marshalRes.NsPerOp(),
UnmarshalNsOp: unmarshalRes.NsPerOp(),
TotalNsOp: marshalRes.NsPerOp() + unmarshalRes.NsPerOp(),
UnsafeStringUnmarshal: bench.UnsafeStringUnmarshal,
BufferReuseMarshal: bench.BufferReuseMarshal,
SerializationSize: int64(marshalRes.Extra["B/serial"]),
MarshalAllocBytes: marshalRes.AllocedBytesPerOp(),
UnmarshalAllocBytes: unmarshalRes.AllocedBytesPerOp(),
TotalAllocBytes: marshalRes.AllocedBytesPerOp() +
unmarshalRes.AllocedBytesPerOp(),
MarshalAllocs: marshalRes.AllocsPerOp(),
UnmarshalAllocs: unmarshalRes.AllocsPerOp(),
TotalAllocs: marshalRes.AllocsPerOp() + unmarshalRes.AllocsPerOp(),
TimeSupport: string(bench.TimeSupport),
APIKind: string(bench.APIKind),
URL: bench.URL,
Notes: strings.Join(bench.Notes, "\n"),
}
}

if !generateReport {
return nil
}

bytes, err := json.MarshalIndent(data, "", "\t")
if err != nil {
return err
}
f, err := os.Create("report/data.js")
if err != nil {
return err
}
if _, err = f.Write([]byte("var data = ")); err != nil {
return err
}
if _, err = f.Write(bytes); err != nil {
return err
}
if _, err = f.Write([]byte(";")); err != nil {
return err
}

fmt.Printf("\nSaved report to report/data.js !\n\n")
return f.Close()
}
19 changes: 7 additions & 12 deletions benchmarks_test.go → benchmark_test.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,28 @@
package goserbench
package main

import (
"fmt"
"os"
"testing"

"github.com/alecthomas/go_serialization_benchmarks/goserbench"
)

var (
validate = os.Getenv("VALIDATE") != ""
)

func TestMessage(t *testing.T) {
fmt.Print(`A test suite for benchmarking various Go serialization methods.
func BenchmarkSerializers(b *testing.B) {
fmt.Printf(`A test suite for benchmarking various Go serialization methods.
See README.md for details on running the benchmarks.
`)
}
Validating = %t
`, *validate)

func BenchmarkSerializers(b *testing.B) {
for i := range benchmarkCases {
bc := benchmarkCases[i]
b.Run("marshal/"+bc.Name, func(b *testing.B) {
goserbench.BenchMarshalSmallStruct(b, bc.New())
})
b.Run("unmarshal/"+bc.Name, func(b *testing.B) {
goserbench.BenchUnmarshalSmallStruct(b, bc.New(), validate)
goserbench.BenchUnmarshalSmallStruct(b, bc.New(), *validate)
})
}
}
12 changes: 2 additions & 10 deletions benchmarks.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package goserbench
package main

import (
"github.com/alecthomas/go_serialization_benchmarks/goserbench"
Expand Down Expand Up @@ -460,18 +460,10 @@ var benchmarkCases = []BenchmarkCase{
URL: "github.com/chmike/ditp",
New: idr.NewIDRSerializer,

TimeSupport: TSFullTzOffset,
APIKind: AKManual,
Notes: []string{"Low level IDR encoding demo"},
}, {
Name: "idr/reuse",
URL: "github.com/chmike/ditp",
New: idr.NewIDRSerializerReuse,

BufferReuseMarshal: true,
TimeSupport: TSFullTzOffset,
APIKind: AKManual,
Notes: []string{"Low level IDR encoding demo"},
Notes: []string{"low level IDR encoding demo with same nsec time encoding as benc"},
}, {
Name: "baseline",
URL: "",
Expand Down
96 changes: 8 additions & 88 deletions genreport_test.go
Original file line number Diff line number Diff line change
@@ -1,105 +1,25 @@
// This file is used to generate the report and is ignored by default on tests.
//
// Generate the report by running `go test -tags genreport`.

//go:build genreport

package goserbench
package main

import (
"encoding/json"
"fmt"
"os"
"strings"
"testing"

"github.com/alecthomas/go_serialization_benchmarks/goserbench"
)

type reportLine struct {
Name string `json:"name"`
MarshalIterCount int `json:"marshal_iter_count"`
UnmarshalIterCount int `json:"unmarshal_iter_count"`
TotalIterCount int `json:"total_iter_count"`
UnsafeStringUnmarshal bool `json:"unsafe_string_unmarshal"`
BufferReuseMarshal bool `json:"buffer_reuse_marshal"`
MarshalNsOp int64 `json:"marshal_ns_op"`
UnmarshalNsOp int64 `json:"unmarshal_ns_op"`
TotalNsOp int64 `json:"total_ns_op"`
SerializationSize int64 `json:"serialization_size"`
MarshalAllocBytes int64 `json:"marshal_alloc_bytes"`
UnmarshalAllocBytes int64 `json:"unmarshal_alloc_bytes"`
TotalAllocBytes int64 `json:"total_alloc_bytes"`
MarshalAllocs int64 `json:"marshal_allocs"`
UnmarshalAllocs int64 `json:"unmarshal_allocs"`
TotalAllocs int64 `json:"total_allocs"`
TimeSupport string `json:"time_support"`
APIKind string `json:"api_kind"`
URL string `json:"url"`
Notes string `json:"notes"`
}
func TestGenerateReport(t *testing.T) {
fmt.Printf(`A test suite for benchmarking various Go serialization methods.
func generateReport() error {
data := make([]reportLine, len(benchmarkCases))
for i, bench := range benchmarkCases {
marshalRes := testing.Benchmark(func(b *testing.B) {
goserbench.BenchMarshalSmallStruct(b, bench.New())
})
fmt.Printf("%10s - Marshal - %s %s\n", bench.Name, marshalRes.String(),
marshalRes.MemString())
unmarshalRes := testing.Benchmark(func(b *testing.B) {
goserbench.BenchUnmarshalSmallStruct(b, bench.New(), false)
})
fmt.Printf("%10s - Unmarshal - %s %s\n", bench.Name, unmarshalRes.String(),
unmarshalRes.MemString())
See README.md for details on running the benchmarks.
data[i] = reportLine{
Name: bench.Name,
MarshalIterCount: marshalRes.N,
UnmarshalIterCount: unmarshalRes.N,
TotalIterCount: marshalRes.N + unmarshalRes.N,
MarshalNsOp: marshalRes.NsPerOp(),
UnmarshalNsOp: unmarshalRes.NsPerOp(),
TotalNsOp: marshalRes.NsPerOp() + unmarshalRes.NsPerOp(),
UnsafeStringUnmarshal: bench.UnsafeStringUnmarshal,
BufferReuseMarshal: bench.BufferReuseMarshal,
SerializationSize: int64(marshalRes.Extra["B/serial"]),
MarshalAllocBytes: marshalRes.AllocedBytesPerOp(),
UnmarshalAllocBytes: unmarshalRes.AllocedBytesPerOp(),
TotalAllocBytes: marshalRes.AllocedBytesPerOp() +
unmarshalRes.AllocedBytesPerOp(),
MarshalAllocs: marshalRes.AllocsPerOp(),
UnmarshalAllocs: unmarshalRes.AllocsPerOp(),
TotalAllocs: marshalRes.AllocsPerOp() + unmarshalRes.AllocsPerOp(),
TimeSupport: string(bench.TimeSupport),
APIKind: string(bench.APIKind),
URL: bench.URL,
Notes: strings.Join(bench.Notes, "\n"),
}
}
Validating = %t
Re-Generating Report = true
bytes, err := json.MarshalIndent(data, "", "\t")
if err != nil {
return err
}
f, err := os.Create("report/data.js")
if err != nil {
return err
}
if _, err = f.Write([]byte("var data = ")); err != nil {
return err
}
if _, err = f.Write(bytes); err != nil {
return err
}
if _, err = f.Write([]byte(";")); err != nil {
return err
}
return f.Close()
}
`, *validate)

func TestGenerateReport(t *testing.T) {
err := generateReport()
err := BenchAndReportSerializers(*validate, true)
if err != nil {
t.Fatal(err)
}
Expand Down
29 changes: 29 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"flag"
"fmt"
)

var (
validate = flag.Bool("validate", false, "to validate the correctness of the serializers")
genReport = flag.Bool("genreport", false, "to re-generate the report")
)

func main() {
flag.Parse()

fmt.Printf(`A test suite for benchmarking various Go serialization methods.
See README.md for details on running the benchmarks.
Validating = %t
Re-Generating Report = %t
`, *validate, *genReport)

err := BenchAndReportSerializers(*genReport, *validate)
if err != nil {
panic(err)
}
}

0 comments on commit 702bb70

Please sign in to comment.