Skip to content

Commit

Permalink
add benchmark tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Skyenought committed Dec 20, 2023
1 parent 82f9bfa commit 6dbd526
Show file tree
Hide file tree
Showing 32 changed files with 1,556 additions and 112 deletions.
82 changes: 82 additions & 0 deletions pkg/app/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,49 @@ func TestCloseIdleConnections(t *testing.T) {
}
}

func BenchmarkCloseIdleConnections(b *testing.B) {
opt := config.NewOptions([]config.Option{})
opt.Addr = "unix-test-10000"
opt.Network = "unix"
engine := route.NewEngine(opt)

go engine.Run()
defer func() {
engine.Close()
}()
time.Sleep(time.Millisecond * 500)

b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
c, _ := NewClient(WithDialer(newMockDialerWithCustomFunc(opt.Network, opt.Addr, 1*time.Second, nil)))
if _, _, err := c.Get(context.Background(), nil, "http://google.com"); err != nil {
b.Fatal(err)
}
connsLen := func() int {
c.mLock.Lock()
defer c.mLock.Unlock()

if _, ok := c.m["google.com"]; !ok {
return 0
}
return c.m["google.com"].ConnectionCount()
}

if conns := connsLen(); conns > 1 {
b.Errorf("expected 1 conns got %d", conns)
}

c.CloseIdleConnections()

if conns := connsLen(); conns > 0 {
b.Errorf("expected 0 conns got %d", conns)
}
}
})
}

func TestClientInvalidURI(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -190,6 +233,45 @@ func TestClientGetWithBody(t *testing.T) {
}
}

func BenchmarkClientGetWithBody(b *testing.B) {
opt := config.NewOptions([]config.Option{})
opt.Addr = "unix-test-10002"
opt.Network = "unix"
engine := route.NewEngine(opt)
engine.GET("/", func(c context.Context, ctx *app.RequestContext) {
body := ctx.Request.Body()
ctx.Write(body) //nolint:errcheck
})
go engine.Run()
defer func() {
engine.Close()
}()
time.Sleep(time.Millisecond * 500)

c, _ := NewClient(WithDialer(newMockDialerWithCustomFunc(opt.Network, opt.Addr, 1*time.Second, nil)))
req, res := protocol.AcquireRequest(), protocol.AcquireResponse()
defer func() {
protocol.ReleaseRequest(req)
protocol.ReleaseResponse(res)
}()
req.Header.SetMethod(consts.MethodGet)
req.SetRequestURI("http://example.com")
req.SetBodyString("test")

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
err := c.Do(context.Background(), req, res)
if err != nil {
b.Fatal(err)
}
if len(res.Body()) == 0 {
b.Fatal("missing request body")
}
res.Reset()
}
}

func TestClientPostBodyStream(t *testing.T) {
t.Parallel()

Expand Down
213 changes: 213 additions & 0 deletions pkg/app/context_timing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package app

import (
"bytes"
"compress/gzip"
"compress/zlib"
"errors"
"io"
"testing"

"github.com/cloudwego/hertz/pkg/common/test/assert"
)

func BenchmarkNewContext(b *testing.B) {
for i := 0; i < b.N; i++ {
c := NewContext(0)
c.Reset()
}
}

// go test -v -run=^$ -bench=BenchmarkCtxJSON -benchmem -count=4
func BenchmarkCtxJSON(b *testing.B) {
ctx := NewContext(0)
defer ctx.Reset()
type SomeStruct struct {
Name string
Age uint8
}
data := SomeStruct{
Name: "Grame",
Age: 20,
}
b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
ctx.JSON(200, &data)
}
}

func BenchmarkCtxString(b *testing.B) {
c := NewContext(0)
defer c.Reset()
s := "Hello, World!"
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
c.String(200, s)
}
}

// go test -v -run=^$ -bench=BenchmarkCtxBody -benchmem -count=4
func BenchmarkCtxBody(b *testing.B) {
ctx := NewContext(0)
defer ctx.Reset()
data := []byte("hello world")
ctx.Request.SetBodyRaw(data)
for n := 0; n < b.N; n++ {
_ = ctx.Request.Body()
}
assert.DeepEqual(b, data, ctx.Request.Body())
}

// go test -v -run=^$ -bench=BenchmarkCtxBodyWithCompression -benchmem -count=4
func BenchmarkCtxBodyWithCompression(b *testing.B) {
encodingErr := errors.New("failed to encoding data")
var (
compressGzip = func(data []byte) ([]byte, error) {
var buf bytes.Buffer
writer := gzip.NewWriter(&buf)
if _, err := writer.Write(data); err != nil {
return nil, encodingErr
}
if err := writer.Flush(); err != nil {
return nil, encodingErr
}
if err := writer.Close(); err != nil {
return nil, encodingErr
}
return buf.Bytes(), nil
}
compressDeflate = func(data []byte) ([]byte, error) {
var buf bytes.Buffer
writer := zlib.NewWriter(&buf)
if _, err := writer.Write(data); err != nil {
return nil, encodingErr
}
if err := writer.Flush(); err != nil {
return nil, encodingErr
}
if err := writer.Close(); err != nil {
return nil, encodingErr
}
return buf.Bytes(), nil
}
)
compressionTests := []struct {
contentEncoding string
compressWriter func([]byte) ([]byte, error)
}{
{
contentEncoding: "gzip",
compressWriter: compressGzip,
},
{
contentEncoding: "gzip,invalid",
compressWriter: compressGzip,
},
{
contentEncoding: "deflate",
compressWriter: compressDeflate,
},
{
contentEncoding: "gzip,deflate",
compressWriter: func(data []byte) ([]byte, error) {
var (
buf bytes.Buffer
writer interface {
io.WriteCloser
Flush() error
}
err error
)
// deflate
{
writer = zlib.NewWriter(&buf)
if _, err = writer.Write(data); err != nil {
return nil, encodingErr
}
if err = writer.Flush(); err != nil {
return nil, encodingErr
}
if err = writer.Close(); err != nil {
return nil, encodingErr
}
}

data = make([]byte, buf.Len())
copy(data, buf.Bytes())
buf.Reset()

// gzip
{
writer = gzip.NewWriter(&buf)
if _, err = writer.Write(data); err != nil {
return nil, encodingErr
}
if err = writer.Flush(); err != nil {
return nil, encodingErr
}
if err = writer.Close(); err != nil {
return nil, encodingErr
}
}

return buf.Bytes(), nil
},
},
}

for _, ct := range compressionTests {
b.Run(ct.contentEncoding, func(b *testing.B) {
c := NewContext(0)
defer c.Reset()
const input = "john=doe"

c.Request.Header.Set("Content-Encoding", ct.contentEncoding)
compressedBody, err := ct.compressWriter([]byte(input))
assert.DeepEqual(b, nil, err)

c.Request.SetBody(compressedBody)
for i := 0; i < b.N; i++ {
_ = c.Request.Body()
}
})
}
}

func BenchmarkCtxWrite(b *testing.B) {
c := NewContext(0)
byt := []byte("Hello, World!")
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = c.Write(byt)
}
}

func BenchmarkCtxWriteString(b *testing.B) {
c := NewContext(0)
defer c.Reset()
s := "Hello, World!"
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = c.WriteString(s)
}
}
Loading

0 comments on commit 6dbd526

Please sign in to comment.