From: Matt Joiner Date: Wed, 18 Mar 2015 07:12:46 +0000 (+1100) Subject: data/blob: Change store eviction to LRU, from random replacement X-Git-Tag: v1.0.0~1277 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=8d58fc28f6f46bba670d159bbba98c7fc8457bf9;p=btrtrc.git data/blob: Change store eviction to LRU, from random replacement It works *much* better for torrenting with a readahead window. When we want to avoid downloading, we want to avoid downloading lots of dispersed pieces. --- diff --git a/data/blob/atime_darwin.go b/data/blob/atime_darwin.go new file mode 100644 index 00000000..33091d59 --- /dev/null +++ b/data/blob/atime_darwin.go @@ -0,0 +1,12 @@ +package blob + +import ( + "os" + "syscall" + "time" +) + +func accessTime(fi os.FileInfo) time.Time { + ts := fi.Sys().(*syscall.Stat_t).Atimespec + return time.Unix(ts.Sec, ts.Nano()) +} diff --git a/data/blob/atime_linux.go b/data/blob/atime_linux.go new file mode 100644 index 00000000..3bcc0548 --- /dev/null +++ b/data/blob/atime_linux.go @@ -0,0 +1,12 @@ +package blob + +import ( + "os" + "syscall" + "time" +) + +func accessTime(fi os.FileInfo) time.Time { + ts := fi.Sys().(*syscall.Stat_t).Atim + return time.Unix(ts.Sec, ts.Nano()) +} diff --git a/data/blob/store.go b/data/blob/store.go index 766129f3..cb8f2aa8 100644 --- a/data/blob/store.go +++ b/data/blob/store.go @@ -10,6 +10,8 @@ import ( "math/rand" "os" "path/filepath" + "sort" + "time" dataPkg "bitbucket.org/anacrolix/go.torrent/data" "github.com/anacrolix/libtorgo/metainfo" @@ -133,6 +135,36 @@ func (me *store) removeCompleted(name string) (err error) { return } +type fileInfoSorter struct { + fis []os.FileInfo +} + +func (me fileInfoSorter) Len() int { + return len(me.fis) +} + +func lastTime(fi os.FileInfo) (ret time.Time) { + ret = fi.ModTime() + atime := accessTime(fi) + if atime.After(ret) { + ret = atime + } + return +} + +func (me fileInfoSorter) Less(i, j int) bool { + return lastTime(me.fis[i]).Before(lastTime(me.fis[j])) +} + +func (me fileInfoSorter) Swap(i, j int) { + me.fis[i], me.fis[j] = me.fis[j], me.fis[i] +} + +func sortFileInfos(fis []os.FileInfo) { + sorter := fileInfoSorter{fis} + sort.Sort(sorter) +} + func (me *store) makeSpace(space int64) error { if me.capacity < 0 { return nil @@ -148,12 +180,11 @@ func (me *store) makeSpace(space int64) error { for _, fi := range fis { size += fi.Size() } + sortFileInfos(fis) for size > me.capacity-space { - i := rand.Intn(len(fis)) - me.removeCompleted(fis[i].Name()) - size -= fis[i].Size() - fis[i] = fis[len(fis)-1] - fis = fis[:len(fis)-1] + me.removeCompleted(fis[0].Name()) + size -= fis[0].Size() + fis = fis[1:] } return nil }