Refactor pool stats

This commit is contained in:
Alexander Neumann 2015-02-08 13:40:11 +01:00
parent d5dccd746e
commit c884704bce
2 changed files with 78 additions and 67 deletions

View file

@ -178,5 +178,6 @@ func main() {
os.Exit(1)
}
// restic.PoolAlloc()
// this prints some statistics for memory management using the debug package
restic.PoolAlloc()
}

142
pools.go
View file

@ -1,103 +1,113 @@
package restic
import "sync"
import (
"sync"
"github.com/restic/restic/debug"
)
type poolStats struct {
m sync.Mutex
mget map[string]int
mput map[string]int
mmax map[string]int
get int
put int
max int
}
func (s *poolStats) Get(k string) {
s.m.Lock()
defer s.m.Unlock()
s.get += 1
cur := s.get - s.put
if cur > s.max {
s.max = cur
}
if k != "" {
if _, ok := s.mget[k]; !ok {
s.mget[k] = 0
s.mput[k] = 0
s.mmax[k] = 0
}
s.mget[k]++
cur = s.mget[k] - s.mput[k]
if cur > s.mmax[k] {
s.mmax[k] = cur
}
}
}
func (s *poolStats) Put(k string) {
s.m.Lock()
defer s.m.Unlock()
s.put += 1
if k != "" {
s.mput[k]++
}
}
func newPoolStats() *poolStats {
return &poolStats{
mget: make(map[string]int),
mput: make(map[string]int),
mmax: make(map[string]int),
}
}
var (
chunkPool = sync.Pool{New: newChunkBuf}
nodePool = sync.Pool{New: newNode}
chunkStats = newPoolStats()
nodeStats = newPoolStats()
)
type alloc_stats struct {
m sync.Mutex
alloc_map map[string]int
free_map map[string]int
alloc int
free int
new int
all int
max int
}
var (
chunk_stats alloc_stats
node_stats alloc_stats
)
func init() {
chunk_stats.alloc_map = make(map[string]int)
chunk_stats.free_map = make(map[string]int)
}
func newChunkBuf() interface{} {
chunk_stats.m.Lock()
chunk_stats.new += 1
chunk_stats.m.Unlock()
// create buffer for iv, data and hmac
return make([]byte, maxCiphertextSize)
}
func newNode() interface{} {
node_stats.m.Lock()
node_stats.new += 1
node_stats.m.Unlock()
// create buffer for iv, data and hmac
return new(Node)
}
func GetChunkBuf(s string) []byte {
chunk_stats.m.Lock()
if _, ok := chunk_stats.alloc_map[s]; !ok {
chunk_stats.alloc_map[s] = 0
}
chunk_stats.alloc_map[s] += 1
chunk_stats.all += 1
if chunk_stats.all > chunk_stats.max {
chunk_stats.max = chunk_stats.all
}
chunk_stats.m.Unlock()
chunkStats.Get(s)
return chunkPool.Get().([]byte)
}
func FreeChunkBuf(s string, buf []byte) {
chunk_stats.m.Lock()
if _, ok := chunk_stats.free_map[s]; !ok {
chunk_stats.free_map[s] = 0
}
chunk_stats.free_map[s] += 1
chunk_stats.all -= 1
chunk_stats.m.Unlock()
chunkStats.Put(s)
chunkPool.Put(buf)
}
func GetNode() *Node {
node_stats.m.Lock()
node_stats.alloc += 1
node_stats.all += 1
if node_stats.all > node_stats.max {
node_stats.max = node_stats.all
}
node_stats.m.Unlock()
nodeStats.Get("")
return nodePool.Get().(*Node)
}
func FreeNode(n *Node) {
node_stats.m.Lock()
node_stats.all -= 1
node_stats.free += 1
node_stats.m.Unlock()
nodeStats.Put("")
nodePool.Put(n)
}
func PoolAlloc() {
// fmt.Fprintf(os.Stderr, "alloc max: %d, new: %d\n", chunk_stats.max, chunk_stats.new)
// for k, v := range chunk_stats.alloc_map {
// fmt.Fprintf(os.Stderr, "alloc[%s] %d, free %d diff: %d\n", k, v, chunk_stats.free_map[k], v-chunk_stats.free_map[k])
// }
debug.Log("pools.PoolAlloc", "pool stats for chunk: get %d, put %d, diff %d, max %d\n", chunkStats.get, chunkStats.put, chunkStats.get-chunkStats.put, chunkStats.max)
for k, v := range chunkStats.mget {
debug.Log("pools.PoolAlloc", "pool stats for chunk[%s]: get %d, put %d, diff %d, max %d\n", k, v, chunkStats.mput[k], v-chunkStats.mput[k], chunkStats.mmax[k])
}
// fmt.Fprintf(os.Stderr, "nodes alloc max: %d, new: %d\n", node_stats.max, node_stats.new)
// fmt.Fprintf(os.Stderr, "alloc %d, free %d diff: %d\n", node_stats.alloc, node_stats.free, node_stats.alloc-node_stats.free)
debug.Log("pools.PoolAlloc", "pool stats for node: get %d, put %d, diff %d, max %d\n", nodeStats.get, nodeStats.put, nodeStats.get-nodeStats.put, nodeStats.max)
for k, v := range nodeStats.mget {
debug.Log("pools.PoolAlloc", "pool stats for node[%s]: get %d, put %d, diff %d, max %d\n", k, v, nodeStats.mput[k], v-nodeStats.mput[k], nodeStats.mmax[k])
}
}