|
|
@ -3,6 +3,7 @@ package needle_map |
|
|
|
import ( |
|
|
|
"fmt" |
|
|
|
"math" |
|
|
|
"slices" |
|
|
|
"sort" |
|
|
|
"sync" |
|
|
|
|
|
|
@ -22,9 +23,10 @@ type CompactNeedleValue struct { |
|
|
|
size types.Size |
|
|
|
} |
|
|
|
|
|
|
|
type Chunk uint64 |
|
|
|
type CompactMapSegment struct { |
|
|
|
list []CompactNeedleValue |
|
|
|
chunk int |
|
|
|
chunk Chunk |
|
|
|
firstKey CompactKey |
|
|
|
lastKey CompactKey |
|
|
|
} |
|
|
@ -32,10 +34,10 @@ type CompactMapSegment struct { |
|
|
|
type CompactMap struct { |
|
|
|
sync.RWMutex |
|
|
|
|
|
|
|
segments map[int]*CompactMapSegment |
|
|
|
segments map[Chunk]*CompactMapSegment |
|
|
|
} |
|
|
|
|
|
|
|
func (ck CompactKey) Key(chunk int) types.NeedleId { |
|
|
|
func (ck CompactKey) Key(chunk Chunk) types.NeedleId { |
|
|
|
return (types.NeedleId(SegmentChunkSize) * types.NeedleId(chunk)) + types.NeedleId(ck) |
|
|
|
} |
|
|
|
|
|
|
@ -49,16 +51,15 @@ func (co CompactOffset) Offset() types.Offset { |
|
|
|
return types.BytesToOffset(co[:]) |
|
|
|
} |
|
|
|
|
|
|
|
func (cnv CompactNeedleValue) NeedleValue(chunk int) NeedleValue { |
|
|
|
key := cnv.key.Key(chunk) |
|
|
|
func (cnv CompactNeedleValue) NeedleValue(chunk Chunk) NeedleValue { |
|
|
|
return NeedleValue{ |
|
|
|
Key: key, |
|
|
|
Key: cnv.key.Key(chunk), |
|
|
|
Offset: cnv.offset.Offset(), |
|
|
|
Size: cnv.size, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func newCompactMapSegment(chunk int) *CompactMapSegment { |
|
|
|
func newCompactMapSegment(chunk Chunk) *CompactMapSegment { |
|
|
|
return &CompactMapSegment{ |
|
|
|
list: []CompactNeedleValue{}, |
|
|
|
chunk: chunk, |
|
|
@ -176,7 +177,7 @@ func (cs *CompactMapSegment) delete(key types.NeedleId) types.Size { |
|
|
|
|
|
|
|
func NewCompactMap() *CompactMap { |
|
|
|
return &CompactMap{ |
|
|
|
segments: map[int]*CompactMapSegment{}, |
|
|
|
segments: map[Chunk]*CompactMapSegment{}, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -197,6 +198,9 @@ func (cm *CompactMap) Cap() int { |
|
|
|
} |
|
|
|
|
|
|
|
func (cm *CompactMap) String() string { |
|
|
|
if cm.Len() == 0 { |
|
|
|
return "empty" |
|
|
|
} |
|
|
|
return fmt.Sprintf( |
|
|
|
"%d/%d elements on %d segments, %.02f%% efficiency", |
|
|
|
cm.Len(), cm.Cap(), len(cm.segments), |
|
|
@ -204,7 +208,7 @@ func (cm *CompactMap) String() string { |
|
|
|
} |
|
|
|
|
|
|
|
func (cm *CompactMap) segmentForKey(key types.NeedleId) *CompactMapSegment { |
|
|
|
chunk := int(key / SegmentChunkSize) |
|
|
|
chunk := Chunk(key / SegmentChunkSize) |
|
|
|
if cs, ok := cm.segments[chunk]; ok { |
|
|
|
return cs |
|
|
|
} |
|
|
@ -251,11 +255,11 @@ func (cm *CompactMap) AscendingVisit(visit func(NeedleValue) error) error { |
|
|
|
cm.RLock() |
|
|
|
defer cm.RUnlock() |
|
|
|
|
|
|
|
chunks := []int{} |
|
|
|
chunks := []Chunk{} |
|
|
|
for c := range cm.segments { |
|
|
|
chunks = append(chunks, c) |
|
|
|
} |
|
|
|
sort.Ints(chunks) |
|
|
|
slices.Sort(chunks) |
|
|
|
|
|
|
|
for _, c := range chunks { |
|
|
|
cs := cm.segments[c] |
|
|
|