Skip to content

Commit a2217bd

Browse files
committed
chore: migrate from wrapped sync.Pool to HashTrieMap
This should lower memory consumption because HashTrieMap doesn't use any and doesn't have double maps. Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
1 parent 8a7a0d4 commit a2217bd

File tree

3 files changed

+27
-31
lines changed

3 files changed

+27
-31
lines changed

.golangci.yml

+13-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
22
#
3-
# Generated on 2024-05-19T19:39:10Z by kres dccd292.
3+
# Generated on 2024-05-28T08:54:28Z by kres a914cae.
44

55
# options for analysis running
66
run:
@@ -13,8 +13,8 @@ run:
1313
# output configuration options
1414
output:
1515
formats:
16-
- format: colored-line-number
17-
path: stdout
16+
- format: colored-line-number
17+
path: stdout
1818
print-issued-lines: true
1919
print-linter-name: true
2020
uniq-by-line: true
@@ -94,17 +94,21 @@ linters-settings:
9494
cyclop:
9595
# the maximal code complexity to report
9696
max-complexity: 20
97-
# depguard:
98-
# Main:
99-
# deny:
100-
# - github.com/OpenPeeDeeP/depguard # this is just an example
97+
depguard:
98+
rules:
99+
prevent_unmaintained_packages:
100+
list-mode: lax # allow unless explicitly denied
101+
files:
102+
- $all
103+
deny:
104+
- pkg: io/ioutil
105+
desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil"
101106

102107
linters:
103108
enable-all: true
104109
disable-all: false
105110
fast: false
106111
disable:
107-
- exhaustivestruct
108112
- exhaustruct
109113
- err113
110114
- forbidigo
@@ -120,30 +124,17 @@ linters:
120124
- mnd
121125
- nestif
122126
- nonamedreturns
123-
- nosnakecase
124127
- paralleltest
125128
- tagalign
126129
- tagliatelle
127130
- thelper
128-
- typecheck
129131
- varnamelen
130132
- wrapcheck
131-
- depguard # Disabled because starting with golangci-lint 1.53.0 it doesn't allow denylist alone anymore
132133
- testifylint # complains about our assert recorder and has a number of false positives for assert.Greater(t, thing, 1)
133134
- protogetter # complains about us using Value field on typed spec, instead of GetValue which has a different signature
134135
- perfsprint # complains about us using fmt.Sprintf in non-performance critical code, updating just kres took too long
135-
# abandoned linters for which golangci shows the warning that the repo is archived by the owner
136-
- deadcode
137-
- golint
138-
- ifshort
139-
- interfacer
140-
- maligned
141-
- scopelint
142-
- structcheck
143-
- varcheck
144-
# disabled as it seems to be broken - goes into imported libraries and reports issues there
145-
- musttag
146136
- goimports # same as gci
137+
- musttag # seems to be broken - goes into imported libraries and reports issues there
147138

148139
issues:
149140
exclude: [ ]

internal/state/snapshot.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package state
77

88
import (
9+
"fmt"
910
"slices"
1011

1112
"github.com/siderolabs/gen/xslices"
@@ -23,7 +24,7 @@ func (state *State) ExportClusterSnapshots(f func(snapshot *storagepb.ClusterSna
2324
// reuse the same snapshotin each iteration
2425
clusterSnapshot := &storagepb.ClusterSnapshot{}
2526

26-
state.clusters.Range(func(_ string, cluster *Cluster) bool {
27+
state.clusters.Enumerate(func(_ string, cluster *Cluster) bool {
2728
snapshotCluster(cluster, clusterSnapshot)
2829

2930
err = f(clusterSnapshot)
@@ -50,7 +51,10 @@ func (state *State) ImportClusterSnapshots(f func() (*storagepb.ClusterSnapshot,
5051

5152
cluster := clusterFromSnapshot(clusterSnapshot)
5253

53-
state.clusters.Store(cluster.id, cluster)
54+
_, loaded := state.clusters.LoadOrStore(cluster.id, cluster)
55+
if loaded {
56+
return fmt.Errorf("cluster %q already exists", cluster.id)
57+
}
5458
}
5559

5660
return nil

internal/state/state.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import (
1111
"time"
1212

1313
prom "github.com/prometheus/client_golang/prometheus"
14-
"github.com/siderolabs/gen/containers"
14+
"github.com/siderolabs/gen/concurrent"
1515
"go.uber.org/zap"
1616
)
1717

1818
// State keeps the discovery service state.
19-
type State struct { //nolint:govet
20-
clusters containers.SyncMap[string, *Cluster]
19+
type State struct {
20+
clusters *concurrent.HashTrieMap[string, *Cluster]
2121
logger *zap.Logger
2222

2323
mClustersDesc *prom.Desc
@@ -32,7 +32,8 @@ type State struct { //nolint:govet
3232
// NewState create new instance of State.
3333
func NewState(logger *zap.Logger) *State {
3434
return &State{
35-
logger: logger,
35+
clusters: concurrent.NewHashTrieMap[string, *Cluster](),
36+
logger: logger,
3637
mClustersDesc: prom.NewDesc(
3738
"discovery_state_clusters",
3839
"The current number of clusters in the state.",
@@ -84,12 +85,12 @@ func (state *State) GetCluster(id string) *Cluster {
8485

8586
// GarbageCollect recursively each cluster, and remove empty clusters.
8687
func (state *State) GarbageCollect(now time.Time) (removedClusters, removedAffiliates int) {
87-
state.clusters.Range(func(key string, cluster *Cluster) bool {
88+
state.clusters.Enumerate(func(key string, cluster *Cluster) bool {
8889
ra, empty := cluster.GarbageCollect(now)
8990
removedAffiliates += ra
9091

9192
if empty {
92-
state.clusters.Delete(key)
93+
state.clusters.CompareAndDelete(key, cluster)
9394
state.logger.Debug("cluster removed", zap.String("cluster_id", key))
9495

9596
removedClusters++
@@ -137,7 +138,7 @@ func (state *State) RunGC(ctx context.Context, logger *zap.Logger, interval time
137138
}
138139

139140
func (state *State) stats() (clusters, affiliates, endpoints, subscriptions int) {
140-
state.clusters.Range(func(_ string, cluster *Cluster) bool {
141+
state.clusters.Enumerate(func(_ string, cluster *Cluster) bool {
141142
clusters++
142143

143144
a, e, s := cluster.stats()

0 commit comments

Comments
 (0)