Skip to content

Commit db2bd06

Browse files
committed
part: Minimize empty Set and Map space usage
Drop the tree when the map or set becomes empty. Signed-off-by: Jussi Maki <[email protected]>
1 parent 10b1722 commit db2bd06

File tree

2 files changed

+37
-17
lines changed

2 files changed

+37
-17
lines changed

part/map.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ type mapKVPair[K, V any] struct {
3232
// This is not implemented as a method on Map[K,V] as hash maps require the
3333
// comparable constraint and we do not need to limit Map[K, V] to that.
3434
func FromMap[K comparable, V any](m Map[K, V], hm map[K]V) Map[K, V] {
35+
if len(hm) == 0 {
36+
return Map[K, V]{}
37+
}
38+
3539
m.ensureTree()
3640
txn := m.tree.Txn()
3741
for k, v := range hm {
@@ -79,6 +83,9 @@ func (m Map[K, V]) Delete(key K) Map[K, V] {
7983
// Map is a struct passed by value, so we can modify
8084
// it without changing the caller's view of it.
8185
m.tree = txn.CommitOnly()
86+
if m.tree.Len() == 0 {
87+
m.tree = nil
88+
}
8289
}
8390
return m
8491
}
@@ -256,6 +263,9 @@ func (m *Map[K, V]) UnmarshalYAML(value *yaml.Node) error {
256263
if value.Kind != yaml.SequenceNode {
257264
return fmt.Errorf("%T.UnmarshalYAML: expected sequence", m)
258265
}
266+
if len(value.Content) == 0 {
267+
return nil
268+
}
259269
m.ensureTree()
260270
txn := m.tree.Txn()
261271
for _, e := range value.Content {

part/set.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,29 @@ type Set[T any] struct {
2727
// NewSet creates a new set of T.
2828
// The value type T must be registered with RegisterKeyType.
2929
func NewSet[T any](values ...T) Set[T] {
30-
s := Set[T]{tree: New[T](RootOnlyWatch, NoCache)}
31-
s.toBytes = lookupKeyType[T]()
32-
if len(values) > 0 {
33-
txn := s.tree.Txn()
34-
for _, v := range values {
35-
txn.Insert(s.toBytes(v), v)
36-
}
37-
s.tree = txn.CommitOnly()
30+
if len(values) == 0 {
31+
return Set[T]{}
32+
}
33+
s := Set[T]{}
34+
s.ensureTree()
35+
txn := s.tree.Txn()
36+
for _, v := range values {
37+
txn.Insert(s.toBytes(v), v)
3838
}
39+
s.tree = txn.CommitOnly()
3940
return s
4041
}
4142

42-
// Set a value. Returns a new set. Original is unchanged.
43-
func (s Set[T]) Set(v T) Set[T] {
43+
func (s *Set[T]) ensureTree() {
4444
if s.tree == nil {
45-
return NewSet(v)
45+
s.tree = New[T](RootOnlyWatch, NoCache)
4646
}
47+
s.toBytes = lookupKeyType[T]()
48+
}
49+
50+
// Set a value. Returns a new set. Original is unchanged.
51+
func (s Set[T]) Set(v T) Set[T] {
52+
s.ensureTree()
4753
txn := s.tree.Txn()
4854
txn.Insert(s.toBytes(v), v)
4955
s.tree = txn.CommitOnly() // As Set is passed by value we can just modify it.
@@ -59,6 +65,9 @@ func (s Set[T]) Delete(v T) Set[T] {
5965
txn := s.tree.Txn()
6066
txn.Delete(s.toBytes(v))
6167
s.tree = txn.CommitOnly()
68+
if s.tree.Len() == 0 {
69+
s.tree = nil
70+
}
6271
return s
6372
}
6473

@@ -186,9 +195,8 @@ func (s *Set[T]) UnmarshalJSON(data []byte) error {
186195
return fmt.Errorf("%T.UnmarshalJSON: expected '[' got %v", s, t)
187196
}
188197

189-
if s.tree == nil {
190-
*s = NewSet[T]()
191-
}
198+
*s = Set[T]{}
199+
s.ensureTree()
192200
txn := s.tree.Txn()
193201

194202
for dec.More() {
@@ -200,6 +208,9 @@ func (s *Set[T]) UnmarshalJSON(data []byte) error {
200208
txn.Insert(s.toBytes(x), x)
201209
}
202210
s.tree = txn.CommitOnly()
211+
if s.tree.Len() == 0 {
212+
s.tree = nil
213+
}
203214

204215
t, err = dec.Token()
205216
if err != nil {
@@ -221,9 +232,8 @@ func (s *Set[T]) UnmarshalYAML(value *yaml.Node) error {
221232
return fmt.Errorf("%T.UnmarshalYAML: expected sequence", s)
222233
}
223234

224-
if s.tree == nil {
225-
*s = NewSet[T]()
226-
}
235+
*s = Set[T]{}
236+
s.ensureTree()
227237
txn := s.tree.Txn()
228238

229239
for _, e := range value.Content {

0 commit comments

Comments
 (0)