Skip to content

Commit

Permalink
Merge pull request #1 from SupunS/custom-maps
Browse files Browse the repository at this point in the history
Add map perf test
  • Loading branch information
SupunS authored Feb 18, 2021
2 parents 2bc2e25 + f017f88 commit fa7bf6f
Show file tree
Hide file tree
Showing 11 changed files with 362 additions and 8 deletions.
3 changes: 0 additions & 3 deletions go-parser/go.mod

This file was deleted.

3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module go_play

go 1.15
135 changes: 135 additions & 0 deletions go_maps/map_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package go_maps

import (
"fmt"
"sync"
"testing"
"time"

"go_play/go_maps/maps"
)

const N = 100_000
const M = 50

var keys = [N]string{}

type foo struct {
once sync.Once
}

func TestMaps(t *testing.T) {
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)
}
106 changes: 106 additions & 0 deletions go_maps/maps/string_map_1.go
Original file line number Diff line number Diff line change
@@ -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)
}
102 changes: 102 additions & 0 deletions go_maps/maps/string_map_2.go
Original file line number Diff line number Diff line change
@@ -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)
//}
File renamed without changes.
2 changes: 1 addition & 1 deletion go-parser/lexer/lexer.go → go_parser/lexer/lexer.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package lexer

import (
"testGo/readers"
"go_play/go_parser/readers"
)

// Lexer represents a lexer instance
Expand Down
File renamed without changes.
9 changes: 5 additions & 4 deletions go-parser/main.go → go_parser/main.go
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
10 changes: 10 additions & 0 deletions go_parser/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package go_parser

import (
"fmt"
"testing"
)

func TestMain(m *testing.M) {
fmt.Println("Hello")
}
File renamed without changes.

0 comments on commit fa7bf6f

Please sign in to comment.