intern protocol names
Ideally, we'd store a bitmap. But we'll have to think through how we want that
to play out with the datastore-backed peerstore (maybe move the `*Protocols`
methods down to the backend implementation?).
@@ -10,6 +10,9 @@ import (
var _ Peerstore = (*peerstore)(nil)
+const maxInternedProtocols = 256
+const maxInternedProtocolSize = 96
+
type peerstore struct {
Metrics
@@ -19,6 +22,7 @@ type peerstore struct {
// lock for protocol information, separate from datastore lock
protolock sync.Mutex
+ internedProtocols map[string]string
}
// NewPeerstore creates a data structure that stores peer data, backed by the
@@ -29,6 +33,7 @@ func NewPeerstore(kb KeyBook, ab AddrBook, md PeerMetadata) Peerstore {
AddrBook: ab,
PeerMetadata: md,
Metrics: NewMetrics(),
+ internedProtocols: make(map[string]string),
}
}
@@ -75,13 +80,30 @@ func (ps *peerstore) PeerInfo(p peer.ID) PeerInfo {
}
}
+func (ps *peerstore) internProtocol(s string) string {
+ if len(s) > maxInternedProtocolSize {
+ return s
+ }
+
+ if interned, ok := ps.internedProtocols[s]; ok {
+ return interned
+ }
+
+ if len(ps.internedProtocols) >= maxInternedProtocols {
+ ps.internedProtocols = make(map[string]string, maxInternedProtocols)
+ }
+
+ ps.internedProtocols[s] = s
+ return s
+}
+
func (ps *peerstore) SetProtocols(p peer.ID, protos ...string) error {
ps.protolock.Lock()
defer ps.protolock.Unlock()
- protomap := make(map[string]struct{})
+ protomap := make(map[string]struct{}, len(protos))
for _, proto := range protos {
- protomap[proto] = struct{}{}
+ protomap[ps.internProtocol(proto)] = struct{}{}
}
return ps.Put(p, "protocols", protomap)
@@ -96,7 +118,7 @@ func (ps *peerstore) AddProtocols(p peer.ID, protos ...string) error {
}
for _, proto := range protos {
- protomap[proto] = struct{}{}
+ protomap[ps.internProtocol(proto)] = struct{}{}
}
return ps.Put(p, "protocols", protomap)
@@ -127,8 +149,8 @@ func (ps *peerstore) GetProtocols(p peer.ID) ([]string, error) {
return nil, err
}
- var out []string
- for k, _ := range pmap {
+ out := make([]string, 0, len(pmap))
+ for k := range pmap {
out = append(out, k)
}
@@ -143,7 +165,7 @@ func (ps *peerstore) SupportsProtocols(p peer.ID, protos ...string) ([]string, e
return nil, err
}
- var out []string
+ out := make([]string, 0, len(protos))
for _, proto := range protos {
if _, ok := pmap[proto]; ok {
out = append(out, proto)
