Commit 83ba0346 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Plug memory leak in bufferpool code: reused buffers should also be in

the handed-out table.
parent 2b9f0042
...@@ -4,8 +4,11 @@ import ( ...@@ -4,8 +4,11 @@ import (
"sync" "sync"
"fmt" "fmt"
"unsafe" "unsafe"
"log"
) )
var _ = log.Println
// This implements a pool of buffers that returns slices with capacity // This implements a pool of buffers that returns slices with capacity
// (2^e * PAGESIZE) for e=0,1,... which have possibly been used, and // (2^e * PAGESIZE) for e=0,1,... which have possibly been used, and
// may contain random contents. // may contain random contents.
...@@ -17,6 +20,10 @@ type BufferPool struct { ...@@ -17,6 +20,10 @@ type BufferPool struct {
// start of slice -> exponent. // start of slice -> exponent.
outstandingBuffers map[uintptr]uint outstandingBuffers map[uintptr]uint
// Total count of created buffers. Handy for finding memory
// leaks.
createdBuffers int
} }
// Returns the smallest E such that 2^E >= Z. // Returns the smallest E such that 2^E >= Z.
...@@ -71,6 +78,13 @@ func (me *BufferPool) addBuffer(slice []byte, exp uint) { ...@@ -71,6 +78,13 @@ func (me *BufferPool) addBuffer(slice []byte, exp uint) {
} }
func (me *BufferPool) AllocCount() int {
me.lock.Lock()
defer me.lock.Unlock()
return me.createdBuffers
}
func (me *BufferPool) AllocBuffer(size uint32) []byte { func (me *BufferPool) AllocBuffer(size uint32) []byte {
sz := int(size) sz := int(size)
if sz < PAGESIZE { if sz < PAGESIZE {
...@@ -87,12 +101,13 @@ func (me *BufferPool) AllocBuffer(size uint32) []byte { ...@@ -87,12 +101,13 @@ func (me *BufferPool) AllocBuffer(size uint32) []byte {
b := me.getBuffer(exp) b := me.getBuffer(exp)
if b != nil { if b == nil {
me.createdBuffers++
b = make([]byte, size, rounded)
} else {
b = b[:size] b = b[:size]
return b
} }
b = make([]byte, size, rounded)
me.outstandingBuffers[uintptr(unsafe.Pointer(&b[0]))] = exp me.outstandingBuffers[uintptr(unsafe.Pointer(&b[0]))] = exp
return b return b
} }
...@@ -103,9 +118,9 @@ func (me *BufferPool) FreeBuffer(slice []byte) { ...@@ -103,9 +118,9 @@ func (me *BufferPool) FreeBuffer(slice []byte) {
if cap(slice) < PAGESIZE { if cap(slice) < PAGESIZE {
return return
} }
slice = slice[:cap(slice)] slice = slice[:cap(slice)]
key := uintptr(unsafe.Pointer(&slice[0])) key := uintptr(unsafe.Pointer(&slice[0]))
me.lock.Lock() me.lock.Lock()
defer me.lock.Unlock() defer me.lock.Unlock()
exp, ok := me.outstandingBuffers[key] exp, ok := me.outstandingBuffers[key]
......
...@@ -3,7 +3,6 @@ package fuse ...@@ -3,7 +3,6 @@ package fuse
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"expvar"
"fmt" "fmt"
"log" "log"
"os" "os"
...@@ -240,18 +239,8 @@ func (me *MountState) OperationCounts() map[string]int64 { ...@@ -240,18 +239,8 @@ func (me *MountState) OperationCounts() map[string]int64 {
} }
func (me *MountState) Stats() string { func (me *MountState) Stats() string {
var lines []string return fmt.Sprintf("buffer alloc count %d\nbuffers %v",
me.buffers.AllocCount(), me.buffers.String())
// TODO - bufferpool should use expvar.
lines = append(lines,
fmt.Sprintf("buffers: %v", me.buffers.String()))
for v := range expvar.Iter() {
if strings.HasPrefix(v.Key, "mount") {
lines = append(lines, fmt.Sprintf("%v: %v\n", v.Key, v.Value))
}
}
return strings.Join(lines, "\n")
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment