From 54e195b94ec3e9c87f6e37fb4f1219ca86ab0559 Mon Sep 17 00:00:00 2001 From: Supun Setunga Date: Thu, 18 Feb 2021 11:30:52 +0530 Subject: [PATCH 1/2] Add map perf test --- maps/go.mod | 3 + maps/main.go | 133 ++++++++++++++++++++++++++++++++++++++ maps/maps/string_map_1.go | 106 ++++++++++++++++++++++++++++++ maps/maps/string_map_2.go | 102 +++++++++++++++++++++++++++++ 4 files changed, 344 insertions(+) create mode 100644 maps/go.mod create mode 100644 maps/main.go create mode 100644 maps/maps/string_map_1.go create mode 100644 maps/maps/string_map_2.go diff --git a/maps/go.mod b/maps/go.mod new file mode 100644 index 0000000..dce7644 --- /dev/null +++ b/maps/go.mod @@ -0,0 +1,3 @@ +module testGo + +go 1.15 diff --git a/maps/main.go b/maps/main.go new file mode 100644 index 0000000..81548c4 --- /dev/null +++ b/maps/main.go @@ -0,0 +1,133 @@ +package main + +import ( + "fmt" + "sync" + "testGo/maps" + "time" +) + +const N = 100_000 +const M = 50 + +var keys = [N]string{} + +type foo struct { + once sync.Once +} +func main() { + var f foo = foo{} + + f.once.Do(func() { + fmt.Println("Running once") + }) + + f.once.Do(func() { + fmt.Println("Running twice") + }) + + //for i := 0 ; i < N ; i++ { + // key := fmt.Sprintf("%d", i) + // keys[i] = key + //} + // + //// Set + //fmt.Println("Set:") + //inbuiltMapInsert() + //customMapInsert() + //customFastMapInsert() + // + //// Get + //fmt.Println("\nGet:") + //inbuiltMapGet() + //customMapGet() + //customFastMapGet() + + fmt.Println("Done!") +} + +func inbuiltMapInsert(){ + + start := time.Now() + for i := 0; i < M; i++ { + builtinMap := map[string]int{} + for i := 0; i < N; i++ { + builtinMap[keys[i]] = i + } + } + + fmt.Println("go map:", time.Now().Sub(start) / M) +} + +func customMapInsert() { + start := time.Now() + for i := 0; i < M; i++ { + stringIntMap := maps.NewStringIntOrderedMap() + for i := 0; i < N; i++ { + stringIntMap.Set(keys[i], i) + } + } + + fmt.Println("custom map:", time.Now().Sub(start) / M) +} + +func customFastMapInsert() { + start := time.Now() + for i := 0; i < M; i++ { + stringIntMap := maps.NewStringIntOrderedFastMap() + for i := 0; i < N; i++ { + stringIntMap.Set(keys[i], i) + } + } + + fmt.Println("fast map:", time.Now().Sub(start) / M) +} + + +func inbuiltMapGet(){ + builtinMap := map[string]int{} + for i := 0; i < N; i++ { + builtinMap[keys[i]] = i + } + + start := time.Now() + for i := 0; i < M; i++ { + for i := 0; i < N; i++ { + _ = builtinMap[keys[i]] + } + } + + fmt.Println("go map:", time.Now().Sub(start) / M) +} + +func customMapGet() { + stringIntMap := maps.NewStringIntOrderedMap() + for i := 0; i < N; i++ { + stringIntMap.Set(keys[i], i) + } + + start := time.Now() + for i := 0; i < M; i++ { + for i := 0; i < N; i++ { + stringIntMap.Get(keys[i]) + } + } + + fmt.Println("custom map:", time.Now().Sub(start) / M) +} + +func customFastMapGet() { + stringIntMap := maps.NewStringIntOrderedFastMap() + for i := 0; i < N; i++ { + stringIntMap.Set(keys[i], i) + } + + start := time.Now() + for i := 0; i < M; i++ { + for i := 0; i < N; i++ { + stringIntMap.Get(keys[i]) + } + } + + fmt.Println("fast map:", time.Now().Sub(start) / M) +} \ No newline at end of file diff --git a/maps/maps/string_map_1.go b/maps/maps/string_map_1.go new file mode 100644 index 0000000..1481cdd --- /dev/null +++ b/maps/maps/string_map_1.go @@ -0,0 +1,106 @@ +package maps + +import "container/list" + +// StringIntOrderedMap +// +type StringIntOrderedMap struct { + pairs map[string]*StringIntPair + list *list.List +} + +// NewStringIntOrderedMap creates a new StringIntOrderedMap. +func NewStringIntOrderedMap() *StringIntOrderedMap { + return &StringIntOrderedMap{ + pairs: make(map[string]*StringIntPair), + list: list.New(), + } +} + +// Get returns the value associated with the given key. +// Returns nil if not found. +// The second return value indicates if the key is present in the map. +func (om *StringIntOrderedMap) Get(key string) (int, bool) { + if pair, present := om.pairs[key]; present { + return pair.Value, present + } + return 0, false +} + +// GetPair returns the key-value pair associated with the given key. +// Returns nil if not found. +func (om *StringIntOrderedMap) GetPair(key string) *StringIntPair { + return om.pairs[key] +} + +// Set sets the key-value pair, and returns what `Get` would have returned +// on that key prior to the call to `Set`. +func (om *StringIntOrderedMap) Set(key string, value int) (int, bool) { + if pair, present := om.pairs[key]; present { + oldValue := pair.Value + pair.Value = value + return oldValue, true + } + + pair := &StringIntPair{ + Key: key, + Value: value, + } + pair.element = om.list.PushBack(pair) + om.pairs[key] = pair + + return 0, false +} + +// Delete removes the key-value pair, and returns what `Get` would have returned +// on that key prior to the call to `Delete`. +func (om *StringIntOrderedMap) Delete(key string) (int, bool) { + if pair, present := om.pairs[key]; present { + om.list.Remove(pair.element) + delete(om.pairs, key) + return pair.Value, true + } + + return 0, false +} + +// Len returns the length of the ordered map. +func (om *StringIntOrderedMap) Len() int { + return len(om.pairs) +} + +// Oldest returns a pointer to the oldest pair. +func (om *StringIntOrderedMap) Oldest() *StringIntPair { + return listElementToPair(om.list.Front()) +} + +// Newest returns a pointer to the newest pair. +func (om *StringIntOrderedMap) Newest() *StringIntPair { + return listElementToPair(om.list.Back()) +} + +// StringIntPair +// +type StringIntPair struct { + Key string + Value int + + element *list.Element +} + +// Next returns a pointer to the next pair. +func (p *StringIntPair) Next() *StringIntPair { + return listElementToPair(p.element.Next()) +} + +// Prev returns a pointer to the previous pair. +func (p *StringIntPair) Prev() *StringIntPair { + return listElementToPair(p.element.Prev()) +} + +func listElementToPair(element *list.Element) *StringIntPair { + if element == nil { + return nil + } + return element.Value.(*StringIntPair) +} diff --git a/maps/maps/string_map_2.go b/maps/maps/string_map_2.go new file mode 100644 index 0000000..0b191d4 --- /dev/null +++ b/maps/maps/string_map_2.go @@ -0,0 +1,102 @@ +package maps + +// StringIntOrderedMap +// +type StringIntOrderedFastMap struct { + pairs map[string]int + entries [] Entry +} + +// NewStringIntOrderedMap creates a new StringIntOrderedMap. +func NewStringIntOrderedFastMap() *StringIntOrderedFastMap { + return &StringIntOrderedFastMap{ + pairs: make(map[string]int), + entries: []Entry{}, + } +} + +// Get returns the value associated with the given key. +// Returns nil if not found. +// The second return value indicates if the key is present in the map. +func (om *StringIntOrderedFastMap) Get(key string) (int, bool) { + if index, present := om.pairs[key]; present { + return om.entries[index].Value, present + } + + return 0, false +} + +//// GetPair returns the key-value pair associated with the given key. +//// Returns nil if not found. +//func (om *StringIntOrderedFastMap) GetPair(key string) *StringIntPair { +// return om.pairs[key] +//} + +// Set sets the key-value pair, and returns what `Get` would have returned +// on that key prior to the call to `Set`. +func (om *StringIntOrderedFastMap) Set(key string, value int) (int, bool) { + if index, present := om.pairs[key]; present { + oldValue := om.entries[index].Value + om.entries[index].Value = value + return oldValue, true + } + + pair := Entry{ + Key: key, + Value: value, + } + om.entries = append(om.entries, pair) + om.pairs[key] = len(om.entries) - 1 + return 0, false +} + +// Delete removes the key-value pair, and returns what `Get` would have returned +// on that key prior to the call to `Delete`. +//func (om *StringIntOrderedFastMap) Delete(key string) (int, bool) { +// if pair, present := om.pairs[key]; present { +// om.entries.Remove(pair.element) +// delete(om.pairs, key) +// return pair.Value, true +// } +// +// return 0, false +//} + +// Len returns the length of the ordered map. +func (om *StringIntOrderedFastMap) Len() int { + return len(om.pairs) +} + +//// Oldest returns a pointer to the oldest pair. +//func (om *StringIntOrderedFastMap) Oldest() *StringIntPair { +// return listElementToPair2(om.entries.Front()) +//} +// +//// Newest returns a pointer to the newest pair. +//func (om *StringIntOrderedFastMap) Newest() *StringIntPair { +// return listElementToPair2(om.entries.Back()) +//} + +// StringIntPair +// +type Entry struct { + Key string + Value int +} + +//// Next returns a pointer to the next pair. +//func (p *StringIntPair) Next() *StringIntPair { +// return listElementToPair2(p.element.Next()) +//} +// +//// Prev returns a pointer to the previous pair. +//func (p *StringIntPair) Prev() *StringIntPair { +// return listElementToPair2(p.element.Prev()) +//} +// +//func listElementToPair2(element *entries.Element) *StringIntPair { +// if element == nil { +// return nil +// } +// return element.Value.(*StringIntPair) +//} From 8f53d2af944b5b670751658f0552bd003db77a53 Mon Sep 17 00:00:00 2001 From: Supun Setunga Date: Thu, 18 Feb 2021 11:59:48 +0530 Subject: [PATCH 2/2] Rstructure the repo --- go-parser/go.mod | 3 -- go.mod | 3 ++ maps/main.go => go_maps/map_test.go | 28 ++++++++++--------- {maps => go_maps}/maps/string_map_1.go | 0 {maps => go_maps}/maps/string_map_2.go | 0 {go-parser => go_parser}/README.md | 0 {go-parser => go_parser}/lexer/lexer.go | 2 +- {go-parser => go_parser}/lexer/tokens.go | 0 {go-parser => go_parser}/main.go | 9 +++--- go_parser/main_test.go | 10 +++++++ .../readers/char_reader.go | 0 maps/go.mod | 3 -- 12 files changed, 34 insertions(+), 24 deletions(-) delete mode 100644 go-parser/go.mod create mode 100644 go.mod rename maps/main.go => go_maps/map_test.go (80%) rename {maps => go_maps}/maps/string_map_1.go (100%) rename {maps => go_maps}/maps/string_map_2.go (100%) rename {go-parser => go_parser}/README.md (100%) rename {go-parser => go_parser}/lexer/lexer.go (98%) rename {go-parser => go_parser}/lexer/tokens.go (100%) rename {go-parser => go_parser}/main.go (74%) create mode 100644 go_parser/main_test.go rename {go-parser => go_parser}/readers/char_reader.go (100%) delete mode 100644 maps/go.mod diff --git a/go-parser/go.mod b/go-parser/go.mod deleted file mode 100644 index dce7644..0000000 --- a/go-parser/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module testGo - -go 1.15 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2e3118d --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module go_play + +go 1.15 diff --git a/maps/main.go b/go_maps/map_test.go similarity index 80% rename from maps/main.go rename to go_maps/map_test.go index 81548c4..3ddcd3d 100644 --- a/maps/main.go +++ b/go_maps/map_test.go @@ -1,10 +1,12 @@ -package main +package go_maps import ( "fmt" "sync" - "testGo/maps" + "testing" "time" + + "go_play/go_maps/maps" ) const N = 100_000 @@ -15,7 +17,8 @@ var keys = [N]string{} type foo struct { once sync.Once } -func main() { + +func TestMaps(t *testing.T) { var f foo = foo{} f.once.Do(func() { @@ -46,7 +49,7 @@ func main() { fmt.Println("Done!") } -func inbuiltMapInsert(){ +func inbuiltMapInsert() { start := time.Now() for i := 0; i < M; i++ { @@ -56,7 +59,7 @@ func inbuiltMapInsert(){ } } - fmt.Println("go map:", time.Now().Sub(start) / M) + fmt.Println("go map:", time.Now().Sub(start)/M) } func customMapInsert() { @@ -68,7 +71,7 @@ func customMapInsert() { } } - fmt.Println("custom map:", time.Now().Sub(start) / M) + fmt.Println("custom map:", time.Now().Sub(start)/M) } func customFastMapInsert() { @@ -80,11 +83,10 @@ func customFastMapInsert() { } } - fmt.Println("fast map:", time.Now().Sub(start) / M) + fmt.Println("fast map:", time.Now().Sub(start)/M) } - -func inbuiltMapGet(){ +func inbuiltMapGet() { builtinMap := map[string]int{} for i := 0; i < N; i++ { builtinMap[keys[i]] = i @@ -97,7 +99,7 @@ func inbuiltMapGet(){ } } - fmt.Println("go map:", time.Now().Sub(start) / M) + fmt.Println("go map:", time.Now().Sub(start)/M) } func customMapGet() { @@ -113,7 +115,7 @@ func customMapGet() { } } - fmt.Println("custom map:", time.Now().Sub(start) / M) + fmt.Println("custom map:", time.Now().Sub(start)/M) } func customFastMapGet() { @@ -129,5 +131,5 @@ func customFastMapGet() { } } - fmt.Println("fast map:", time.Now().Sub(start) / M) -} \ No newline at end of file + fmt.Println("fast map:", time.Now().Sub(start)/M) +} diff --git a/maps/maps/string_map_1.go b/go_maps/maps/string_map_1.go similarity index 100% rename from maps/maps/string_map_1.go rename to go_maps/maps/string_map_1.go diff --git a/maps/maps/string_map_2.go b/go_maps/maps/string_map_2.go similarity index 100% rename from maps/maps/string_map_2.go rename to go_maps/maps/string_map_2.go diff --git a/go-parser/README.md b/go_parser/README.md similarity index 100% rename from go-parser/README.md rename to go_parser/README.md diff --git a/go-parser/lexer/lexer.go b/go_parser/lexer/lexer.go similarity index 98% rename from go-parser/lexer/lexer.go rename to go_parser/lexer/lexer.go index 9c6d3f6..4d97ccf 100755 --- a/go-parser/lexer/lexer.go +++ b/go_parser/lexer/lexer.go @@ -1,7 +1,7 @@ package lexer import ( - "testGo/readers" + "go_play/go_parser/readers" ) // Lexer represents a lexer instance diff --git a/go-parser/lexer/tokens.go b/go_parser/lexer/tokens.go similarity index 100% rename from go-parser/lexer/tokens.go rename to go_parser/lexer/tokens.go diff --git a/go-parser/main.go b/go_parser/main.go similarity index 74% rename from go-parser/main.go rename to go_parser/main.go index 003adf9..50430d5 100644 --- a/go-parser/main.go +++ b/go_parser/main.go @@ -1,14 +1,15 @@ -package main +package go_parser import ( "fmt" - lex "testGo/lexer" - "testGo/readers" + + lex "go_play/go_parser/lexer" + "go_play/go_parser/readers" ) func main() { fmt.Println("Hello") - reader := readers.NewCharReader("/Users/supun/Supun/testGo/main.go") + reader := readers.NewCharReader("/Users/supun/Supun/testGo/map_test.go") lexer := lex.NewLexer(&reader) for !reader.IsEOF() { diff --git a/go_parser/main_test.go b/go_parser/main_test.go new file mode 100644 index 0000000..40b0245 --- /dev/null +++ b/go_parser/main_test.go @@ -0,0 +1,10 @@ +package go_parser + +import ( + "fmt" + "testing" +) + +func TestMain(m *testing.M) { + fmt.Println("Hello") +} diff --git a/go-parser/readers/char_reader.go b/go_parser/readers/char_reader.go similarity index 100% rename from go-parser/readers/char_reader.go rename to go_parser/readers/char_reader.go diff --git a/maps/go.mod b/maps/go.mod deleted file mode 100644 index dce7644..0000000 --- a/maps/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module testGo - -go 1.15