mirror of https://github.com/jlelse/GoBlog
parent
3c6c234233
commit
46548df638
@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// cacheRecorder is an implementation of http.ResponseWriter
|
||||
type cacheRecorder struct {
|
||||
item *cacheItem
|
||||
}
|
||||
|
||||
func newCacheRecorder() *cacheRecorder {
|
||||
return &cacheRecorder{
|
||||
item: &cacheItem{
|
||||
code: http.StatusOK,
|
||||
header: make(http.Header),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cacheRecorder) finish() (ci *cacheItem) {
|
||||
ci = c.item
|
||||
c.item = nil
|
||||
return
|
||||
}
|
||||
|
||||
// Header implements http.ResponseWriter.
|
||||
func (rw *cacheRecorder) Header() http.Header {
|
||||
if rw.item == nil {
|
||||
return nil
|
||||
}
|
||||
return rw.item.header
|
||||
}
|
||||
|
||||
// Write implements http.ResponseWriter.
|
||||
func (rw *cacheRecorder) Write(buf []byte) (int, error) {
|
||||
if rw.item == nil {
|
||||
return 0, nil
|
||||
}
|
||||
rw.item.body = append(rw.item.body, buf...)
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
// WriteString implements io.StringWriter.
|
||||
func (rw *cacheRecorder) WriteString(str string) (int, error) {
|
||||
return rw.Write([]byte(str))
|
||||
}
|
||||
|
||||
// WriteHeader implements http.ResponseWriter.
|
||||
func (rw *cacheRecorder) WriteHeader(code int) {
|
||||
if rw.item == nil {
|
||||
return
|
||||
}
|
||||
if code < 100 || code > 999 {
|
||||
panic(fmt.Sprintf("invalid WriteHeader code %v", code))
|
||||
}
|
||||
rw.item.code = code
|
||||
}
|
||||
|
||||
// Flush implements http.Flusher.
|
||||
func (rw *cacheRecorder) Flush() {
|
||||
// Do nothing
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/dgraph-io/ristretto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Benchmark_cacheItem_cost(b *testing.B) {
|
||||
ci := &cacheItem{
|
||||
creationTime: time.Now(),
|
||||
eTag: "abc",
|
||||
code: 200,
|
||||
header: http.Header{
|
||||
"Content-Type": []string{"text/html"},
|
||||
},
|
||||
body: []byte("<html>abcdefghijklmnopqrstuvwxyz</html>"),
|
||||
}
|
||||
b.RunParallel(func(p *testing.PB) {
|
||||
for p.Next() {
|
||||
ci.cost()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cacheItem_cost(t *testing.T) {
|
||||
ci := &cacheItem{
|
||||
header: http.Header{
|
||||
"Content-Type": []string{"text/html"},
|
||||
},
|
||||
body: []byte("<html>abcdefghijklmnopqrstuvwxyz</html>"),
|
||||
eTag: "abc",
|
||||
}
|
||||
bodyLen := len(ci.body)
|
||||
assert.Equal(t, 39, bodyLen)
|
||||
eTagLen := len(ci.eTag)
|
||||
assert.Equal(t, 3, eTagLen)
|
||||
assert.Greater(t, ci.cost(), bodyLen+eTagLen)
|
||||
}
|
||||
|
||||
func Benchmark_cacheKey(b *testing.B) {
|
||||
req := httptest.NewRequest(http.MethodGet, "/abc?abc=def&hij=klm", nil)
|
||||
b.RunParallel(func(p *testing.PB) {
|
||||
for p.Next() {
|
||||
cacheKey(req)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Benchmark_cache_getCache(b *testing.B) {
|
||||
c := &cache{}
|
||||
c.c, _ = ristretto.NewCache(&ristretto.Config{
|
||||
NumCounters: 40 * 1000,
|
||||
MaxCost: 20 * 1000 * 1000,
|
||||
BufferItems: 64,
|
||||
})
|
||||
req := httptest.NewRequest(http.MethodGet, "/abc?abc=def&hij=klm", nil)
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = io.WriteString(w, "abcdefghijklmnopqrstuvwxyz")
|
||||
_, _ = w.Write([]byte("abcdefghijklmnopqrstuvwxyz"))
|
||||
})
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.getCache(strconv.Itoa(i), handler, req)
|
||||
}
|
||||
}
|
Loading…
Reference in new issue