From f68f07d896a677b4709e1c4be9b07364ff7c385b Mon Sep 17 00:00:00 2001 From: James Hillyerd Date: Sat, 20 Oct 2018 20:33:27 -0700 Subject: [PATCH] file: pool index readers to reduce allocs for #122 --- pkg/storage/file/fstore.go | 33 ++++++++++++++++++++++++++++----- pkg/storage/file/mbox.go | 4 +++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/pkg/storage/file/fstore.go b/pkg/storage/file/fstore.go index a52bc36..2eb51c9 100644 --- a/pkg/storage/file/fstore.go +++ b/pkg/storage/file/fstore.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path/filepath" + "sync" "time" "github.com/jhillyerd/inbucket/pkg/config" @@ -40,10 +41,11 @@ func countGenerator(c chan int) { // Store implements DataStore aand is the root of the mail storage // hiearchy. It provides access to Mailbox objects type Store struct { - hashLock storage.HashLock - path string - mailPath string - messageCap int + hashLock storage.HashLock + path string + mailPath string + messageCap int + bufReaderPool sync.Pool } // New creates a new DataStore object using the specified path @@ -60,7 +62,16 @@ func New(cfg config.Storage) (storage.Store, error) { Msg("Error creating dir") } } - return &Store{path: path, mailPath: mailPath, messageCap: cfg.MailboxMsgCap}, nil + return &Store{ + path: path, + mailPath: mailPath, + messageCap: cfg.MailboxMsgCap, + bufReaderPool: sync.Pool{ + New: func() interface{} { + return bufio.NewReader(nil) + }, + }, + }, nil } // AddMessage adds a message to the specified mailbox. @@ -253,6 +264,18 @@ func (fs *Store) mboxFromHash(hash string) *mbox { } } +// getPooledReader pulls a buffered reader from the fs.bufReaderPool +func (fs *Store) getPooledReader(r io.Reader) *bufio.Reader { + br := fs.bufReaderPool.Get().(*bufio.Reader) + br.Reset(r) + return br +} + +// putPooledReader returns a buffered reader to the fs.bufReaderPool +func (fs *Store) putPooledReader(br *bufio.Reader) { + fs.bufReaderPool.Put(br) +} + // generatePrefix converts a Time object into the ISO style format we use // as a prefix for message files. Note: It is used directly by unit // tests. diff --git a/pkg/storage/file/mbox.go b/pkg/storage/file/mbox.go index 8c85145..55f1c9f 100644 --- a/pkg/storage/file/mbox.go +++ b/pkg/storage/file/mbox.go @@ -120,7 +120,9 @@ func (mb *mbox) readIndex() error { } }() // Decode gob data - dec := gob.NewDecoder(bufio.NewReader(file)) + br := mb.store.getPooledReader(file) + defer mb.store.putPooledReader(br) + dec := gob.NewDecoder(br) name := "" if err = dec.Decode(&name); err != nil { return fmt.Errorf("Corrupt mailbox %q: %v", mb.indexPath, err)