Skip to content

Commit

Permalink
Add benchmark and profiling facilities (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
supercaracal authored Feb 5, 2025
1 parent 2f083e7 commit 1979e9b
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 5 deletions.
58 changes: 58 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,61 @@ jobs:
with:
version: "latest"
install-go: false

benchmark:
name: Benchmark
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
check-latest: true

- name: Install dependencies
run: |
sudo apt update
sudo apt install -y libaom-dev
- name: Download modules
run: go mod download

- name: Run benchmark
run: make bench

profiling:
name: Profiling
timeout-minutes: 10
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package: ["handler"]
type: ["cpu", "block", "mem"]
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
check-latest: true

- name: Install dependencies
run: |
sudo apt update
sudo apt install -y libaom-dev
- name: Download modules
run: go mod download

- name: Run profiling
run: make prof
env:
PKG: ${{ matrix.package }}
TYPE: ${{ matrix.type }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,6 @@ vendor/
/server
/fanlin.json
/*.log
/*.out
/*.test
__debug_bin
14 changes: 13 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,20 @@ test:
lint:
@go vet ./...

bench:
@go test -bench=. -benchmem -run=NONE ./...

prof: PKG ?= handler
prof: TYPE ?= mem
prof:
@if [ -z "${PKG}" ]; then echo 'empty variable: PKG'; exit 1; fi
@if [ -z "${TYPE}" ]; then echo 'empty variable: TYPE'; exit 1; fi
@if [ ! -d "./lib/${PKG}" ]; then echo 'package not found: ${PKG}'; exit 1; fi
@go test -bench=. -run=NONE -${TYPE}profile=${TYPE}.out ./lib/${PKG}
@go tool pprof -text -nodecount=10 ./${PKG}.test ${TYPE}.out

clean:
@unlink fanlin.json || true
@rm -f cmd/fanlin/server cmd/fanlin/fanlin.json

.PHONY: build cmd/fanlin/server run test lint clean
.PHONY: build cmd/fanlin/server run test lint bench prof clean
46 changes: 46 additions & 0 deletions lib/handler/handler_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package handler

import (
"io"
"net/http"
"net/url"
"testing"

configure "github.com/livesense-inc/fanlin/lib/conf"
helper "github.com/livesense-inc/fanlin/lib/test"
"github.com/sirupsen/logrus"
)

func TestMakeMetricsHandler(t *testing.T) {
Expand All @@ -26,3 +28,47 @@ func TestMakeMetricsHandler(t *testing.T) {
t.Errorf("want=%d, got=%d", http.StatusOK, w.StatusCode())
}
}

func BenchmarkMainHandler(b *testing.B) {
c := configure.NewConfigure("../test/test_conf9.json")
if c == nil {
b.Fatal("Failed to build config")
}

w := helper.NewNullResponseWriter()
r := &http.Request{
RemoteAddr: "127.0.0.1",
Proto: "HTTP/1.1",
Method: http.MethodGet,
Host: "127.0.0.1:3000",
URL: &url.URL{
Path: "/Lenna.jpg",
RawQuery: func() string {
q := url.Values{}
q.Set("w", "300")
q.Set("h", "200")
return q.Encode()
}(),
},
Header: http.Header{
"Content-Type": []string{"application/x-www-form-urlencoded"},
},
}

stdOut := logrus.New()
stdOut.Out = io.Discard
stdErr := logrus.New()
stdErr.Out = io.Discard
l := map[string]*logrus.Logger{"access": stdOut, "err": stdErr}

b.ResetTimer()
for i := 0; i < b.N; i++ {
MainHandler(w, r, c, l)
if w.StatusCode() != 200 {
b.Fatalf("want: 200, got: %d", w.StatusCode())
}
if w.BodySize() == 0 {
b.Fatal("empty response body")
}
}
}
15 changes: 11 additions & 4 deletions lib/test/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ const (

// NullResponseWriter is a struct
type NullResponseWriter struct {
h http.Header
b io.Writer
sc int
h http.Header
b io.Writer
bSize int
sc int
}

// NewNullResponseWriter returns a instance of NullResponseWriter
func NewNullResponseWriter() *NullResponseWriter {
return &NullResponseWriter{h: http.Header{}, b: io.Discard}
return &NullResponseWriter{h: http.Header{}, b: io.Discard, sc: http.StatusOK}
}

// Header returns headers
Expand All @@ -31,6 +32,7 @@ func (w *NullResponseWriter) Header() http.Header {

// Write writes bytes to response writer
func (w *NullResponseWriter) Write(p []byte) (int, error) {
w.bSize += len(p)
return w.b.Write(p)
}

Expand All @@ -44,6 +46,11 @@ func (w *NullResponseWriter) StatusCode() int {
return w.sc
}

// BodySize returns a size of the body
func (w *NullResponseWriter) BodySize() int {
return w.bSize
}

// NullLogger returns a instance of log.Logger
func NullLogger() *log.Logger {
return log.New(io.Discard, "", 0)
Expand Down
17 changes: 17 additions & 0 deletions lib/test/test_conf9.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"port": 3000,
"max_width": 3000,
"max_height": 3000,
"404_img_path": "../../img/404.png",
"access_log_path": "/dev/null",
"error_log_path": "/dev/null",
"max_clients": 50,
"providers": [
{
"/" : {
"type" : "local",
"src" : "../test/img"
}
}
]
}

0 comments on commit 1979e9b

Please sign in to comment.