Moved ReadMemStats into a background polling function

This will keep profile commands such as SERVER and STATS from
stopping the world.
This commit is contained in:
tidwall 2019-09-03 16:57:49 -07:00
commit 4bd6b4b838
1 changed files with 28 additions and 6 deletions

View File

@ -9,6 +9,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/tidwall/resp"
@ -16,6 +17,30 @@ import (
"github.com/tidwall/tile38/internal/collection"
)
var memStats runtime.MemStats
var memStatsMu sync.Mutex
var memStatsBG bool
// ReadMemStats returns the latest memstats. It provides an instant response.
func readMemStats() runtime.MemStats {
memStatsMu.Lock()
if !memStatsBG {
runtime.ReadMemStats(&memStats)
go func() {
for {
memStatsMu.Lock()
runtime.ReadMemStats(&memStats)
memStatsMu.Unlock()
time.Sleep(time.Second / 5)
}
}()
memStatsBG = true
}
ms := memStats
memStatsMu.Unlock()
return ms
}
func (c *Server) cmdStats(msg *Message) (res resp.Value, err error) {
start := time.Now()
vs := msg.Args[1:]
@ -133,8 +158,7 @@ func (c *Server) basicStats(m map[string]interface{}) {
m["num_points"] = points
m["num_objects"] = objects
m["num_strings"] = strings
var mem runtime.MemStats
runtime.ReadMemStats(&mem)
mem := readMemStats()
avgsz := 0
if points != 0 {
avgsz = int(mem.HeapAlloc) / points
@ -154,9 +178,8 @@ func (c *Server) basicStats(m map[string]interface{}) {
// extStats populates the passed map with extended system/go/tile38 statistics
func (c *Server) extStats(m map[string]interface{}) {
var mem runtime.MemStats
n, _ := runtime.ThreadCreateProfile(nil)
runtime.ReadMemStats(&mem)
mem := readMemStats()
// Go/Memory Stats
@ -326,8 +349,7 @@ func (c *Server) writeInfoClients(w *bytes.Buffer) {
c.connsmu.RUnlock()
}
func (c *Server) writeInfoMemory(w *bytes.Buffer) {
var mem runtime.MemStats
runtime.ReadMemStats(&mem)
mem := readMemStats()
fmt.Fprintf(w, "used_memory:%d\r\n", mem.Alloc) // total number of bytes allocated by Redis using its allocator (either standard libc, jemalloc, or an alternative allocator such as tcmalloc
}
func boolInt(t bool) int {