mirror of https://github.com/restic/restic.git
155 lines
3.3 KiB
Go
155 lines
3.3 KiB
Go
package restic
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"sync"
|
|
|
|
"github.com/restic/restic/chunker"
|
|
"github.com/restic/restic/debug"
|
|
)
|
|
|
|
type poolStats struct {
|
|
m sync.Mutex
|
|
mget map[string]int
|
|
mput map[string]int
|
|
mmax map[string]int
|
|
|
|
new 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}
|
|
chunkerPool = sync.Pool{New: newChunker}
|
|
|
|
chunkStats = newPoolStats()
|
|
nodeStats = newPoolStats()
|
|
chunkerStats = newPoolStats()
|
|
)
|
|
|
|
func newChunkBuf() interface{} {
|
|
chunkStats.m.Lock()
|
|
defer chunkStats.m.Unlock()
|
|
chunkStats.new++
|
|
|
|
// create buffer for iv, data and hmac
|
|
return make([]byte, maxCiphertextSize)
|
|
}
|
|
|
|
func newNode() interface{} {
|
|
nodeStats.m.Lock()
|
|
defer nodeStats.m.Unlock()
|
|
nodeStats.new++
|
|
|
|
// create buffer for iv, data and hmac
|
|
return new(Node)
|
|
}
|
|
|
|
func newChunker() interface{} {
|
|
chunkStats.m.Lock()
|
|
defer chunkStats.m.Unlock()
|
|
chunkStats.new++
|
|
|
|
// create a new chunker with a nil reader
|
|
return chunker.New(nil, chunkerBufSize, sha256.New())
|
|
}
|
|
|
|
func GetChunkBuf(s string) []byte {
|
|
chunkStats.Get(s)
|
|
return chunkPool.Get().([]byte)
|
|
}
|
|
|
|
func FreeChunkBuf(s string, buf []byte) {
|
|
chunkStats.Put(s)
|
|
chunkPool.Put(buf)
|
|
}
|
|
|
|
func GetNode() *Node {
|
|
nodeStats.Get("")
|
|
return nodePool.Get().(*Node)
|
|
}
|
|
|
|
func FreeNode(n *Node) {
|
|
nodeStats.Put("")
|
|
nodePool.Put(n)
|
|
}
|
|
|
|
func GetChunker(s string) *chunker.Chunker {
|
|
chunkerStats.Get(s)
|
|
return chunkerPool.Get().(*chunker.Chunker)
|
|
}
|
|
|
|
func FreeChunker(s string, ch *chunker.Chunker) {
|
|
chunkerStats.Put(s)
|
|
chunkerPool.Put(ch)
|
|
}
|
|
|
|
func PoolAlloc() {
|
|
debug.Log("pools.PoolAlloc", "pool stats for chunk: new %d, get %d, put %d, diff %d, max %d\n",
|
|
chunkStats.new, 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])
|
|
}
|
|
|
|
debug.Log("pools.PoolAlloc", "pool stats for node: new %d, get %d, put %d, diff %d, max %d\n",
|
|
nodeStats.new, 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])
|
|
}
|
|
|
|
debug.Log("pools.PoolAlloc", "pool stats for chunker: new %d, get %d, put %d, diff %d, max %d\n",
|
|
chunkerStats.new, chunkerStats.get, chunkerStats.put, chunkerStats.get-chunkerStats.put, chunkerStats.max)
|
|
for k, v := range chunkerStats.mget {
|
|
debug.Log("pools.PoolAlloc", "pool stats for chunker[%s]: get %d, put %d, diff %d, max %d\n", k, v, chunkerStats.mput[k], v-chunkerStats.mput[k], chunkerStats.mmax[k])
|
|
}
|
|
}
|