mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-24 21:24:05 -08:00
use new unique package to reduce memory duplication of interned labels
when multiple remote writes are configured Signed-off-by: Callum Styan <callumstyan@gmail.com>
This commit is contained in:
parent
75e6497ec1
commit
d3d5e2af0e
2
go.mod
2
go.mod
|
@ -1,6 +1,6 @@
|
|||
module github.com/prometheus/prometheus
|
||||
|
||||
go 1.21.0
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.22.5
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package remote
|
|||
|
||||
import (
|
||||
"sync"
|
||||
"unique"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
|
@ -35,22 +36,20 @@ var noReferenceReleases = promauto.NewCounter(prometheus.CounterOpts{
|
|||
|
||||
type pool struct {
|
||||
mtx sync.RWMutex
|
||||
pool map[string]*entry
|
||||
pool map[unique.Handle[string]]*entry
|
||||
}
|
||||
|
||||
type entry struct {
|
||||
refs atomic.Int64
|
||||
|
||||
s string
|
||||
}
|
||||
|
||||
func newEntry(s string) *entry {
|
||||
return &entry{s: s}
|
||||
func newEntry() *entry {
|
||||
return &entry{}
|
||||
}
|
||||
|
||||
func newPool() *pool {
|
||||
return &pool{
|
||||
pool: map[string]*entry{},
|
||||
pool: map[unique.Handle[string]]*entry{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,27 +59,28 @@ func (p *pool) intern(s string) string {
|
|||
}
|
||||
|
||||
p.mtx.RLock()
|
||||
interned, ok := p.pool[s]
|
||||
h := unique.Make(s)
|
||||
interned, ok := p.pool[h]
|
||||
p.mtx.RUnlock()
|
||||
if ok {
|
||||
interned.refs.Inc()
|
||||
return interned.s
|
||||
return s
|
||||
}
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
if interned, ok := p.pool[s]; ok {
|
||||
if interned, ok := p.pool[h]; ok {
|
||||
interned.refs.Inc()
|
||||
return interned.s
|
||||
return s
|
||||
}
|
||||
|
||||
p.pool[s] = newEntry(s)
|
||||
p.pool[s].refs.Store(1)
|
||||
p.pool[h] = newEntry()
|
||||
p.pool[h].refs.Store(1)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *pool) release(s string) {
|
||||
p.mtx.RLock()
|
||||
interned, ok := p.pool[s]
|
||||
h := unique.Make(s)
|
||||
interned, ok := p.pool[h]
|
||||
p.mtx.RUnlock()
|
||||
|
||||
if !ok {
|
||||
|
@ -98,5 +98,5 @@ func (p *pool) release(s string) {
|
|||
if interned.refs.Load() != 0 {
|
||||
return
|
||||
}
|
||||
delete(p.pool, s)
|
||||
delete(p.pool, h)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
"unique"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -30,7 +31,7 @@ func TestIntern(t *testing.T) {
|
|||
interner := newPool()
|
||||
testString := "TestIntern"
|
||||
interner.intern(testString)
|
||||
interned, ok := interner.pool[testString]
|
||||
interned, ok := interner.pool[unique.Make(testString)]
|
||||
|
||||
require.True(t, ok)
|
||||
require.Equal(t, int64(1), interned.refs.Load(), fmt.Sprintf("expected refs to be 1 but it was %d", interned.refs.Load()))
|
||||
|
@ -41,13 +42,13 @@ func TestIntern_MultiRef(t *testing.T) {
|
|||
testString := "TestIntern_MultiRef"
|
||||
|
||||
interner.intern(testString)
|
||||
interned, ok := interner.pool[testString]
|
||||
interned, ok := interner.pool[unique.Make(testString)]
|
||||
|
||||
require.True(t, ok)
|
||||
require.Equal(t, int64(1), interned.refs.Load(), fmt.Sprintf("expected refs to be 1 but it was %d", interned.refs.Load()))
|
||||
|
||||
interner.intern(testString)
|
||||
interned, ok = interner.pool[testString]
|
||||
interned, ok = interner.pool[unique.Make(testString)]
|
||||
|
||||
require.True(t, ok)
|
||||
require.Equal(t, int64(2), interned.refs.Load(), fmt.Sprintf("expected refs to be 2 but it was %d", interned.refs.Load()))
|
||||
|
@ -58,13 +59,13 @@ func TestIntern_DeleteRef(t *testing.T) {
|
|||
testString := "TestIntern_DeleteRef"
|
||||
|
||||
interner.intern(testString)
|
||||
interned, ok := interner.pool[testString]
|
||||
interned, ok := interner.pool[unique.Make(testString)]
|
||||
|
||||
require.True(t, ok)
|
||||
require.Equal(t, int64(1), interned.refs.Load(), fmt.Sprintf("expected refs to be 1 but it was %d", interned.refs.Load()))
|
||||
|
||||
interner.release(testString)
|
||||
_, ok = interner.pool[testString]
|
||||
_, ok = interner.pool[unique.Make(testString)]
|
||||
require.False(t, ok)
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,7 @@ func TestIntern_MultiRef_Concurrent(t *testing.T) {
|
|||
testString := "TestIntern_MultiRef_Concurrent"
|
||||
|
||||
interner.intern(testString)
|
||||
interned, ok := interner.pool[testString]
|
||||
interned, ok := interner.pool[unique.Make(testString)]
|
||||
require.True(t, ok)
|
||||
require.Equal(t, int64(1), interned.refs.Load(), fmt.Sprintf("expected refs to be 1 but it was %d", interned.refs.Load()))
|
||||
|
||||
|
@ -84,7 +85,7 @@ func TestIntern_MultiRef_Concurrent(t *testing.T) {
|
|||
time.Sleep(time.Millisecond)
|
||||
|
||||
interner.mtx.RLock()
|
||||
interned, ok = interner.pool[testString]
|
||||
interned, ok = interner.pool[unique.Make(testString)]
|
||||
interner.mtx.RUnlock()
|
||||
require.True(t, ok)
|
||||
require.Equal(t, int64(1), interned.refs.Load(), fmt.Sprintf("expected refs to be 1 but it was %d", interned.refs.Load()))
|
||||
|
|
Loading…
Reference in a new issue