Use trick to intern strings with GC for subjString

Signed-off-by: Derek Collison <derek@nats.io>
This commit is contained in:
Derek Collison
2023-04-07 09:14:57 -07:00
parent 2ff6f18ccd
commit 4edb08280f

View File

@@ -4483,13 +4483,35 @@ func (mb *msgBlock) msgFromBuf(buf []byte, sm *StoreMsg, hh hash.Hash64) (*Store
return sm, nil
}
// Used to intern strings for subjects.
// Based on idea from https://github.com/josharian/intern/blob/master/intern.go
var subjPool = sync.Pool{
New: func() any {
return make(map[string]string)
},
}
// Get an interned string from a byte slice.
func subjFromBytes(b []byte) string {
sm := subjPool.Get().(map[string]string)
defer subjPool.Put(sm)
subj, ok := sm[string(b)]
if ok {
return subj
}
s := string(b)
sm[s] = s
return s
}
// Given the `key` byte slice, this function will return the subject
// as a copy of `key` or a configured subject as to minimize memory allocations.
// as an interned string of `key` or a configured subject as to minimize memory allocations.
// Lock should be held.
func (mb *msgBlock) subjString(skey []byte) string {
if len(skey) == 0 {
return _EMPTY_
}
if lsubjs := len(mb.fs.cfg.Subjects); lsubjs > 0 {
if lsubjs == 1 {
// The cast for the comparison does not make a copy
@@ -4504,7 +4526,7 @@ func (mb *msgBlock) subjString(skey []byte) string {
}
}
}
return string(skey)
return subjFromBytes(skey)
}
// LoadMsg will lookup the message by sequence number and return it if found.