From ac1afa19b8d6a8512646631691ac5971fee956a0 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Fri, 5 Dec 2014 00:54:55 -0600 Subject: [PATCH] mmap_span: Avoid allocating the span slice on every use --- cmd/torrent-verify/main.go | 4 ++-- misc.go | 5 +++-- mmap_span/mmap_span.go | 23 +++++++++++------------ torrent.go | 8 +++++--- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/cmd/torrent-verify/main.go b/cmd/torrent-verify/main.go index 3d56e7d3..4206756a 100644 --- a/cmd/torrent-verify/main.go +++ b/cmd/torrent-verify/main.go @@ -33,7 +33,7 @@ func main() { log.Print(err) } defer devZero.Close() - var mMapSpan mmap_span.MMapSpan + var mMapSpan *mmap_span.MMapSpan for _, file := range metaInfo.Info.Files { filename := filepath.Join(append([]string{*dirPath, metaInfo.Info.Name}, file.Path...)...) osFile, err := os.Open(filename) @@ -53,7 +53,7 @@ func main() { log.Printf("file mmap has wrong size: %#v", filename) } osFile.Close() - mMapSpan = append(mMapSpan, goMMap) + mMapSpan.Append(goMMap) } log.Println(len(metaInfo.Info.Files)) log.Println(mMapSpan.Size()) diff --git a/misc.go b/misc.go index 96723ed5..a3240449 100644 --- a/misc.go +++ b/misc.go @@ -125,7 +125,8 @@ func upvertedSingleFileInfoFiles(info *metainfo.Info) []metainfo.FileInfo { return []metainfo.FileInfo{{Length: info.Length, Path: nil}} } -func mmapTorrentData(md *metainfo.Info, location string) (mms mmap_span.MMapSpan, err error) { +func mmapTorrentData(md *metainfo.Info, location string) (mms *mmap_span.MMapSpan, err error) { + mms = &mmap_span.MMapSpan{} defer func() { if err != nil { mms.Close() @@ -170,7 +171,7 @@ func mmapTorrentData(md *metainfo.Info, location string) (mms mmap_span.MMapSpan if int64(len(mMap)) != miFile.Length { panic("mmap has wrong length") } - mms = append(mms, mMap) + mms.Append(mMap) }() if err != nil { return diff --git a/mmap_span/mmap_span.go b/mmap_span/mmap_span.go index 66635a12..37e63af5 100644 --- a/mmap_span/mmap_span.go +++ b/mmap_span/mmap_span.go @@ -14,30 +14,29 @@ func (me segment) Size() int64 { return int64(len(me.MMap)) } -type MMapSpan []gommap.MMap +type MMapSpan struct { + span +} -func (me MMapSpan) span() (s span) { - for _, mmap := range me { - s = append(s, segment{mmap}) - } - return +func (me *MMapSpan) Append(mmap gommap.MMap) { + me.span = append(me.span, segment{mmap}) } func (me MMapSpan) Close() { - for _, mMap := range me { - mMap.UnsafeUnmap() + for _, mMap := range me.span { + mMap.(segment).UnsafeUnmap() } } func (me MMapSpan) Size() (ret int64) { - for _, seg := range me.span() { + for _, seg := range me.span { ret += seg.Size() } return } func (me MMapSpan) ReadAt(p []byte, off int64) (n int, err error) { - me.span().ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) { + me.ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) { _n := copy(p, interval.(segment).MMap[intervalOffset:]) p = p[_n:] n += _n @@ -50,7 +49,7 @@ func (me MMapSpan) ReadAt(p []byte, off int64) (n int, err error) { } func (me MMapSpan) WriteSectionTo(w io.Writer, off, n int64) (written int64, err error) { - me.span().ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) { + me.ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) { var _n int p := interval.(segment).MMap[intervalOffset:] if n < int64(len(p)) { @@ -68,7 +67,7 @@ func (me MMapSpan) WriteSectionTo(w io.Writer, off, n int64) (written int64, err } func (me MMapSpan) WriteAt(p []byte, off int64) (n int, err error) { - me.span().ApplyTo(off, func(iOff int64, i sizer) (stop bool) { + me.ApplyTo(off, func(iOff int64, i sizer) (stop bool) { mMap := i.(segment) _n := copy(mMap.MMap[iOff:], p) // err = mMap.Sync(gommap.MS_ASYNC) diff --git a/torrent.go b/torrent.go index 07f7b0b6..56b738a8 100644 --- a/torrent.go +++ b/torrent.go @@ -60,7 +60,7 @@ type torrent struct { length int64 // Prevent mutations to Data memory maps while in use as they're not safe. dataLock sync.RWMutex - Data mmap_span.MMapSpan + Data *mmap_span.MMapSpan Info *MetaInfo // Active peer connections. @@ -459,8 +459,10 @@ func (t *torrent) Close() (err error) { t.CeaseNetworking() close(t.closing) t.dataLock.Lock() - t.Data.Close() - t.Data = nil + if t.Data != nil { + t.Data.Close() + t.Data = nil + } t.dataLock.Unlock() for _, conn := range t.Conns { conn.Close() -- 2.44.0