From 89f068210f2962387623f090c9e6fb728d79a2a9 Mon Sep 17 00:00:00 2001 From: Yilun Date: Sat, 29 Sep 2018 00:18:15 -0700 Subject: [PATCH] Use go-cache for hashcache Signed-off-by: Yilun --- common/cache.go | 50 +++++++++++++++++++++++++++++++++++++++++++ glide.lock | 6 ++++-- glide.yaml | 1 + net/node/hashcache.go | 41 +++++++++++------------------------ net/node/node.go | 2 +- 5 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 common/cache.go diff --git a/common/cache.go b/common/cache.go new file mode 100644 index 000000000..894e46af1 --- /dev/null +++ b/common/cache.go @@ -0,0 +1,50 @@ +package common + +import ( + "time" + + gocache "github.com/patrickmn/go-cache" +) + +// Cache is an anstract cache layer +type Cache interface { + Add([]byte, interface{}) error + Get([]byte) (interface{}, bool) + Set([]byte, interface{}) error +} + +// GoCache is the caching layer implemented by go-cache. +type GoCache struct { + cache *gocache.Cache +} + +// NewGoCache creates a go-cache cache with a given default expiration duration +// and cleanup interval. +func NewGoCache(defaultExpiration, cleanupInterval time.Duration) *GoCache { + return &GoCache{ + cache: gocache.New(defaultExpiration, cleanupInterval), + } +} + +func (gc *GoCache) byteKeyToStringKey(byteKey []byte) string { + return string(byteKey) +} + +// Add adds an item to the cache only if an item doesn't already exist for the +// given key, or if the existing item has expired. Returns an error otherwise. +func (gc *GoCache) Add(key []byte, value interface{}) error { + return gc.cache.Add(gc.byteKeyToStringKey(key), value, 0) +} + +// Get gets an item from the cache. Returns the item or nil, and a bool +// indicating whether the key was found. +func (gc *GoCache) Get(key []byte) (interface{}, bool) { + return gc.cache.Get(gc.byteKeyToStringKey(key)) +} + +// Set adds an item to the cache, replacing any existing item, using the default +// expiration. +func (gc *GoCache) Set(key []byte, value interface{}) error { + gc.cache.SetDefault(gc.byteKeyToStringKey(key), value) + return nil +} diff --git a/glide.lock b/glide.lock index 898487bf6..32f94f037 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 328f4aade5f3518e7d77e48ae5cddac8de014f8805cff81c1ac8a9ad4574acaa -updated: 2018-09-27T01:31:19.95747456+02:00 +hash: 1f8b9353dfb0b18a20a1da19c19cd864593565d8573619f88f31405d0afb0460 +updated: 2018-09-28T23:15:10.260779-07:00 imports: - name: github.com/bitly/go-simplejson version: da1a8928f709389522c8023062a3739f3b4af419 @@ -33,6 +33,8 @@ imports: version: 577ad0ea8a14b52de7ae9da02c59e5557666248c - name: github.com/nknorg/gopass version: 9ddc09fe41c891b7987acd1bf75f9067a56c17f5 +- name: github.com/patrickmn/go-cache + version: 5633e0862627c011927fa39556acae8b1f1df58a - name: github.com/pborman/uuid version: 1b00554d822231195d1babd97ff4a781231955c9 subpackages: diff --git a/glide.yaml b/glide.yaml index a8d3fb2e6..f52e00961 100644 --- a/glide.yaml +++ b/glide.yaml @@ -29,3 +29,4 @@ import: - package: github.com/jpillora/backoff version: 1.0.0 - package: github.com/nknorg/go-portscanner +- package: github.com/patrickmn/go-cache diff --git a/net/node/hashcache.go b/net/node/hashcache.go index cd3bd6dfd..884c39837 100644 --- a/net/node/hashcache.go +++ b/net/node/hashcache.go @@ -1,47 +1,32 @@ package node import ( - "sync" + "time" - . "github.com/nknorg/nkn/common" + "github.com/nknorg/nkn/common" ) const ( - HashCacheCap = 1000 + HashCacheExpiration = 60 * time.Second + HashCacheCleanupInterval = 1 * time.Second ) type hashCache struct { - sync.RWMutex - cap int - list map[Uint256]struct{} - hashes []Uint256 + cache common.Cache } -func NewHashCache(cap int) *hashCache { +func NewHashCache() *hashCache { return &hashCache{ - cap: cap, - list: make(map[Uint256]struct{}), + cache: common.NewGoCache(HashCacheExpiration, HashCacheCleanupInterval), } } -func (hc *hashCache) addHash(hash Uint256) { - if len(hc.hashes) <= HashCacheCap { - hc.hashes = append(hc.hashes, hash) - } else { - delete(hc.list, hc.hashes[0]) - hc.hashes = append(hc.hashes[1:], hash) - } - hc.list[hash] = struct{}{} +func (hc *hashCache) addHash(hash common.Uint256) { + hc.cache.Set(hash.ToArray(), true) } -func (hc *hashCache) ExistHash(hash Uint256) bool { - hc.Lock() - defer hc.Unlock() - - if _, ok := hc.list[hash]; ok { - return true - } - hc.addHash(hash) - - return false +func (hc *hashCache) ExistHash(hash common.Uint256) bool { + _, ok := hc.cache.Get(hash.ToArray()) + hc.cache.Set(hash.ToArray(), true) + return ok } diff --git a/net/node/node.go b/net/node/node.go index ebdc339e1..2c68cba59 100644 --- a/net/node/node.go +++ b/net/node/node.go @@ -191,7 +191,7 @@ func InitNode(pubKey *crypto.PubKey, ring *chord.Ring) Noder { n.msgHandlerChan = MakeChanQueue(MaxMsgChanNum) n.quit = make(chan bool, 1) n.eventQueue.init() - n.hashCache = NewHashCache(HashCacheCap) + n.hashCache = NewHashCache() n.nodeDisconnectSubscriber = n.eventQueue.GetEvent("disconnect").Subscribe(events.EventNodeDisconnect, n.NodeDisconnected) n.ring = ring