From a012161bc03854d84759d62f188ef114aaa97cba Mon Sep 17 00:00:00 2001 From: qydysky Date: Mon, 22 Feb 2021 20:50:26 +0800 Subject: [PATCH] =?utf8?q?=E5=8F=AF=E8=83=BD=E7=9A=84=E9=80=BB=E8=BE=91?= =?utf8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- map/Map.go | 3 +- map/Map_test.go | 6 +++- tmplKV/tmplK.go | 83 ++++++++++++++++++++++---------------------- tmplKV/tmplK_test.go | 10 +++--- 4 files changed, 53 insertions(+), 49 deletions(-) diff --git a/map/Map.go b/map/Map.go index 48c2f5b..09d1a2b 100644 --- a/map/Map.go +++ b/map/Map.go @@ -103,7 +103,8 @@ func (t *Map) Delete(k interface{}) { t.lock.Lock() delete(t.m, k) - + t.num -= 1 + t.lock.Unlock() } diff --git a/map/Map_test.go b/map/Map_test.go index 73e5219..371525e 100644 --- a/map/Map_test.go +++ b/map/Map_test.go @@ -21,8 +21,12 @@ func Test_customMap(t *testing.T) { return true }) //del - c.Store(0, nil) + c.Delete(0) if v,ok := c.Load(0);ok && v != nil{t.Error(`4`)} + t.Log(c.Len()) + c.Delete(1) + if v,ok := c.Load(1);ok && v != nil{t.Error(`6`)} + t.Log(c.Len()) } func Benchmark_customMap_Set(b *testing.B) { diff --git a/tmplKV/tmplK.go b/tmplKV/tmplK.go index 34ab4cb..9084ef2 100644 --- a/tmplKV/tmplK.go +++ b/tmplKV/tmplK.go @@ -2,7 +2,8 @@ package part import ( "time" - "sync" + "container/list" + syncmap "github.com/qydysky/part/map" idpool "github.com/qydysky/part/idpool" ) @@ -10,10 +11,9 @@ type tmplK struct { SumInDruation int64 Druation int64 now int64 - deleteNum int pool *idpool.Idpool - kvt_map map[string]tmplK_item - sync.RWMutex + kvt_map syncmap.Map + slowBackList *list.List } type tmplK_item struct { @@ -27,8 +27,8 @@ func New_tmplK(SumInDruation,Druation int64) (*tmplK) { s := &tmplK{ SumInDruation:SumInDruation, Druation:Druation, - kvt_map:make(map[string]tmplK_item), pool:idpool.New(), + slowBackList:list.New(), } go func(){ ticker := time.NewTicker(time.Second) @@ -41,51 +41,44 @@ func New_tmplK(SumInDruation,Druation int64) (*tmplK) { } func (s *tmplK) Set(key string) (id uintptr) { - s.Lock() - defer s.Unlock() - if tmp, oks := s.kvt_map[key];oks { - defer s.pool.Put(tmp.uid)//在取得新Id后才put回 - } else if s.SumInDruation >= 0 && s.pool.Len() >= uint(s.SumInDruation){//不为无限&&达到限额 随机替代 - for oldkey,item := range s.kvt_map { - s.kvt_map[key] = tmplK_item{ - kv: item.kv, + if tmp, oks := s.kvt_map.LoadV(key).(tmplK_item);oks { + s.free(tmp.uid) + } else if s.SumInDruation >= 0 && s.freeLen() >= s.SumInDruation{//不为无限&&达到限额 随机替代 + s.kvt_map.Range(func(oldkey,item interface{})(bool){ + id = item.(tmplK_item).kv + s.kvt_map.Store(key, tmplK_item{ + kv: id, kt: s.now, - uid: item.uid, - } - delete(s.kvt_map,oldkey) - return item.kv - } + uid: item.(tmplK_item).uid, + }) + s.kvt_map.Delete(oldkey) + return false + }) + return } Uid := s.pool.Get() - s.kvt_map[key] = tmplK_item{ + s.kvt_map.Store(key, tmplK_item{ kv: Uid.Id, kt: s.now, uid: Uid, - } + }) return Uid.Id } func (s *tmplK) Get(key string) (isLive bool,id uintptr){ - s.RLock() - tmp, ok := s.kvt_map[key] - s.RUnlock() + tmp, ok := s.kvt_map.Load(key) - id = tmp.kv - isLive = ok && s.Druation < 0 || s.now - tmp.kt <= s.Druation + item,_ := tmp.(tmplK_item) + id = item.kv + + isLive = ok && s.Druation < 0 || s.now - item.kt <= s.Druation if !isLive && ok { - s.pool.Put(tmp.uid) - s.Lock() - delete(s.kvt_map,key) - s.deleteNum += 0 - if s.deleteNum > len(s.kvt_map) { - s.deleteNum = 0 - go s.Tidy() - } - s.Unlock() + s.free(item.uid) + s.kvt_map.Delete(key) } return } @@ -95,14 +88,20 @@ func (s *tmplK) Check(key string,id uintptr) bool { return ok && k == id } -func (s *tmplK) Buf() (int64,int) { - return s.now,len(s.kvt_map) +func (s *tmplK) Len() (int64,int) { + return s.now,s.kvt_map.Len() } -func (s *tmplK) Tidy() { - tmp := make(map[string]tmplK_item) - s.Lock() - for k,v := range s.kvt_map {tmp[k] = v} - s.kvt_map = tmp - s.Unlock() +func (s *tmplK) freeLen() (int64) { + return int64(int(s.pool.Len()) + s.slowBackList.Len()) +} + +func (s *tmplK) free(i *idpool.Id) { + s.slowBackList.PushBack(i) + if s.freeLen() > s.SumInDruation { + if el := s.slowBackList.Front();el != nil{ + e := s.slowBackList.Remove(el) + s.pool.Put(e.(*idpool.Id)) + } + } } \ No newline at end of file diff --git a/tmplKV/tmplK_test.go b/tmplKV/tmplK_test.go index 80b7ab2..250980e 100644 --- a/tmplKV/tmplK_test.go +++ b/tmplKV/tmplK_test.go @@ -6,21 +6,21 @@ import ( "testing" ) -func Test_tmplK(t *testing.T) { +func Test_tmplK1(t *testing.T) { s := New_tmplK(1e6, 5) k1 := s.Set("a") if !s.Check("a",k1) {t.Error(`no match1`)} k2 := s.Set("a") if s.Check("a",k1) {t.Error(`match`)} if !s.Check("a",k2) {t.Error(`no match2`)} - if o,p := s.Buf();p != 1 || o - time.Now().Unix() > 1{t.Error(`sum/time no match1`)} + if o,p := s.Len();p != 1 || o - time.Now().Unix() > 1{t.Error(`sum/time no match1`)} - time.Sleep(time.Second*time.Duration(5)) + time.Sleep(time.Second*time.Duration(6)) if s.Check("a",k1) {t.Error(`no TO1`)} - if s.Check("a",k1) {t.Error(`no TO2`)} + if s.Check("a",k2) {t.Error(`no TO2`)} - if o,p := s.Buf();p != 0 || o - time.Now().Unix() > 1{t.Error(`sum/time no match2`)} + if o,p := s.Len();p != 0 || o - time.Now().Unix() > 1{t.Error(`sum/time no match2`,p)} } func Test_tmplK2(t *testing.T) { -- 2.39.2