- Notifications
You must be signed in to change notification settings - Fork0
tommymcguiver/randomnumber
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
http://localhost:8080/random?start=10&end=633
curl -v 'localhost:8080/random?start=10&end=633'
go test -bench .go test -bench . -benchmemgo test -bench Benchmark_ServeHttp -benchmemgo test -bench Benchmark_ServeHttp -benchmem -cpuprofile prof.cpu | tee bench.0go test -bench Benchmark_ServeHttp -benchmem -memprofile prof.mem | tee bench.0benchcmp bench.0 bench.1
go tool pprof randomnumber.test prof.cpu
atomic.AddInt64(&requestCount, 1)func TestServer_HandleRandom_Parallel(t *testing.T) {var wg sync.WaitGroupvar testServer = httptest.NewServer(http.HandlerFunc(HandleRandom))for i := 0; i < 2; i++ {wg.Add(1)go func() {defer wg.Done()res, err := http.Get(testServer.URL + "/random?start=1&end=2000")if err != nil {t.Error(err)return}if res.StatusCode != 200 {t.Error("Status code invalid")return}}()}//Wait until donewg.Wait()}
Builder
var randomBuilder strings.Builderfunc (rn *RandomNumber) MarshalJSON() ([]byte, error) {randomBuilder.Reset()fmt.Fprintf(&randomBuilder, `{"Number":%d}`, rn.Number)return []byte(randomBuilder.String()), nil}
bytes.Buffer
func (rn *RandomNumber) MarshalJSON() ([]byte, error) {buffer := bytes.NewBufferString(`{"Number":`)buffer.WriteString("1}")return buffer.Bytes(), nil}
Extra Alloc
fmt.Fprintf(w, "%s", string(b))
Global RNG
var rng = rand.New(mt19937.New())
Query Mapping
for k, v := range map[string][]string(r.URL.Query()) {switch k {case "start":if len(v) == 1 {start, err = strconv.Atoi(v[0])}if err != nil {w.WriteHeader(http.StatusBadRequest)return}case "end":if len(v) == 1 {end, err = strconv.Atoi(v[0])}if err != nil {w.WriteHeader(http.StatusBadRequest)return}}}
Sync Pool
Is ugly, but for maximum performance ( i.e. 0 allocations at runtime) you can do this.
var randomPool = sync.Pool{New: func() interface{} {return new(RandomNumber)},}var rng = rand.New(mt19937.New())func NewRandomNumber() *RandomNumber {rn := randomPool.Get().(*RandomNumber)defer randomPool.Put(rn)rn.Number = 0rng.Seed(time.Now().UnixNano())rn.Number = rng.Int63()return rn}
Contention
func reset(rw *httptest.ResponseRecorder) {m := rw.HeaderMapfor k := range m {delete(m, k)}body := rw.Bodybody.Reset()*rw = httptest.ResponseRecorder{Body: body,HeaderMap: m,}}func BenchmarkHealthParallel(b *testing.B) {r := httptest.NewRequest("GET", "http://example.com/health", nil)b.RunParallel(func(pb *testing.PB) {rw := httptest.NewRecorder()for pb.Next() {HandleHealth(rw, r)reset(rw)}})}
http://localhost:8080/debug/pprof/
import _ "net/http/pprof"....server := http.DefaultServeMuxserver.HandleFunc("/health", HandleHealth)server.HandleFunc("/random", HandleRandom)log.Println("Starting server...")log.Fatal(http.ListenAndServe(":8080", server))