From d6145b6f11d0909a02d83f27e2d56a7c636f2694 Mon Sep 17 00:00:00 2001 From: Anton Tiurin Date: Wed, 11 Feb 2015 00:46:46 +0300 Subject: [PATCH 1/4] [Set] Use map[interface{}]struct{} to save some amount of memory as struct{} needs 0 memory. Signed-off-by: Anton Tiurin --- set/dict.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/set/dict.go b/set/dict.go index 94f61b6..fd8563d 100644 --- a/set/dict.go +++ b/set/dict.go @@ -29,7 +29,7 @@ var pool = sync.Pool{} // Set is an implementation of ISet using the builtin map type. Set is threadsafe. type Set struct { - items map[interface{}]bool + items map[interface{}]struct{} lock sync.RWMutex flattened []interface{} } @@ -41,7 +41,7 @@ func (set *Set) Add(items ...interface{}) { set.flattened = nil for _, item := range items { - set.items[item] = true + set.items[item] = struct{}{} } } @@ -94,7 +94,7 @@ func (set *Set) Clear() { set.lock.Lock() defer set.lock.Unlock() - set.items = map[interface{}]bool{} + set.items = map[interface{}]struct{}{} } // All returns a bool indicating if all of the supplied items exist in the set. @@ -134,7 +134,7 @@ func (set *Set) Dispose() { func New(items ...interface{}) *Set { set := pool.Get().(*Set) for _, item := range items { - set.items[item] = true + set.items[item] = struct{}{} } return set @@ -143,7 +143,7 @@ func New(items ...interface{}) *Set { func init() { pool.New = func() interface{} { return &Set{ - items: make(map[interface{}]bool, 10), + items: make(map[interface{}]struct{}, 10), } } } From ffc26bd1bedee3fd8e05a8351cc2df0eca2ecc55 Mon Sep 17 00:00:00 2001 From: Anton Tiurin Date: Wed, 11 Feb 2015 00:56:30 +0300 Subject: [PATCH 2/4] [Set] Replace defer (R)Unlock() with direct calling in plain simple methods to speedup Set Signed-off-by: Anton Tiurin --- set/dict.go | 14 ++++++++++---- set/dict_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/set/dict.go b/set/dict.go index fd8563d..ca5f7ed 100644 --- a/set/dict.go +++ b/set/dict.go @@ -59,9 +59,11 @@ func (set *Set) Remove(items ...interface{}) { // Exists returns a bool indicating if the given item exists in the set. func (set *Set) Exists(item interface{}) bool { set.lock.RLock() - defer set.lock.RUnlock() _, ok := set.items[item] + + set.lock.RUnlock() + return ok } @@ -84,17 +86,21 @@ func (set *Set) Flatten() []interface{} { // Len returns the number of items in the set. func (set *Set) Len() int64 { set.lock.RLock() - defer set.lock.RUnlock() - return int64(len(set.items)) + size := int64(len(set.items)) + + set.lock.RUnlock() + + return size } // Clear will remove all items from the set. func (set *Set) Clear() { set.lock.Lock() - defer set.lock.Unlock() set.items = map[interface{}]struct{}{} + + set.lock.Unlock() } // All returns a bool indicating if all of the supplied items exist in the set. diff --git a/set/dict_test.go b/set/dict_test.go index 31e6071..b7965c3 100644 --- a/set/dict_test.go +++ b/set/dict_test.go @@ -176,3 +176,39 @@ func BenchmarkFlatten(b *testing.B) { set.Flatten() } } + +func BenchmarkLen(b *testing.B) { + set := New() + for i := 0; i < 50; i++ { + item := strconv.Itoa(i) + set.Add(item) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + set.Len() + } +} + +func BenchmarkExists(b *testing.B) { + set := New() + set.Add(1) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + set.Exists(1) + } +} + +func BenchmarkClear(b *testing.B) { + set := New() + for i := 0; i < 50; i++ { + item := strconv.Itoa(i) + set.Add(item) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + set.Clear() + } +} From 3fb44b83bed5c831a20bbf4add44f0ae62818704 Mon Sep 17 00:00:00 2001 From: Anton Tiurin Date: Wed, 11 Feb 2015 11:14:33 +0300 Subject: [PATCH 3/4] [Set] Fix BenchmarkClear --- set/dict_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/set/dict_test.go b/set/dict_test.go index b7965c3..36155ac 100644 --- a/set/dict_test.go +++ b/set/dict_test.go @@ -201,13 +201,6 @@ func BenchmarkExists(b *testing.B) { } func BenchmarkClear(b *testing.B) { - set := New() - for i := 0; i < 50; i++ { - item := strconv.Itoa(i) - set.Add(item) - } - - b.ResetTimer() for i := 0; i < b.N; i++ { set.Clear() } From cc09fcce8fb79091d87cee1e5f6f6c6d55259459 Mon Sep 17 00:00:00 2001 From: Anton Tiurin Date: Wed, 11 Feb 2015 16:32:41 +0300 Subject: [PATCH 4/4] [Set] Fix BenchmarkClear again Signed-off-by: Anton Tiurin --- set/dict_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/set/dict_test.go b/set/dict_test.go index 36155ac..8d2ddce 100644 --- a/set/dict_test.go +++ b/set/dict_test.go @@ -201,6 +201,7 @@ func BenchmarkExists(b *testing.B) { } func BenchmarkClear(b *testing.B) { + set := New() for i := 0; i < b.N; i++ { set.Clear() }