initial string deduplication and integer list

This commit is contained in:
Annika Hannig 2022-11-14 22:54:33 +01:00
parent f97a4a7bc8
commit 59f3141f2a
4 changed files with 102 additions and 21 deletions

View File

@ -1,5 +0,0 @@
pgstore:
- per RS table could mitigate insert issue

View File

@ -0,0 +1,42 @@
package pools
import "sync"
// IntNode is a node in the tree.
type IntNode struct {
children []*IntNode
value int
ptr any
}
// IntTree is a tree structure for deduplicating
// lists of integers.
type IntTree struct {
children []*IntNode
}
// Acquire int list
func (t *IntTree) Acquire(list []int) []int {
if len(list) == 0 {
return nil
}
v := list[0]
var node *IntNode
// TODO
for _, c := range t.children {
if c.value == v {
// TODO
}
}
}
// A IntList pool can be used to deduplicate
// lists of integers. Like an AS path.
//
// A Tree datastructure is used.
type IntList struct {
values *IntTree
counter *IntTree
sync.Mutex
}

View File

@ -3,10 +3,12 @@ package pools
import "sync" import "sync"
// String is a pool for strings. // String is a pool for strings.
// This will most likely be a pool for IP addresses.
type String struct { type String struct {
values map[string]*string values map[string]*string
counter map[string]uint counter map[string]uint
top uint top uint
sync.Mutex sync.Mutex
} }
@ -14,7 +16,8 @@ type String struct {
// NewString creates a new string pool // NewString creates a new string pool
func NewString() *String { func NewString() *String {
return &String{ return &String{
values: map[string]*string{}, values: map[string]*string{},
counter: map[string]uint{},
} }
} }
@ -28,22 +31,10 @@ func (p *String) Acquire(s string) *string {
p.values[s] = &s p.values[s] = &s
ptr = &s ptr = &s
} }
// Increment counter and top value p.counter[s] = p.top
cnt, ok := p.counter[s]
if !ok {
cnt = p.top + 1
} else {
cnt = cnt + 1
}
p.counter[s] = cnt
if p.top < cnt {
p.top = cnt
}
return ptr return ptr
} }
// GarbageCollect releases all values, which have not been seen // GarbageCollect releases all values, which have not been seen
// again. // again.
func (p *String) GarbageCollect() uint { func (p *String) GarbageCollect() uint {
@ -57,5 +48,6 @@ func (p *String) GarbageCollect() uint {
released++ released++
} }
} }
p.top++ // Next generation
return released return released
} }

View File

@ -0,0 +1,52 @@
package pools
import (
"fmt"
"testing"
)
func TestAcquireString(t *testing.T) {
p := NewString()
s1 := p.Acquire("hello")
s2 := p.Acquire("hello")
s3 := p.Acquire("world")
s1 = p.Acquire("hello")
if s1 != s2 {
t.Error("expected s1 == s2")
}
t.Log(fmt.Sprintf("s1, s2: %x %x", s1, s2))
if s2 == s3 {
t.Error("expected s2 !== s3")
}
t.Log(fmt.Sprintf("s1, s2: %x %x", s1, s2))
}
func TestGarbageCollectString(t *testing.T) {
p := NewString()
// Gen 1
p.Acquire("hello")
p.Acquire("world")
r := p.GarbageCollect()
if r > 0 {
t.Error("first run should not collect anything.")
}
p.Acquire("hello")
p.Acquire("foo")
r = p.GarbageCollect()
if r != 1 {
t.Error("expected 1 released value")
}
for k := range p.values {
if k == "world" {
t.Error("did not expect to find world here")
}
}
t.Log(p.values)
t.Log(p.counter)
}