graph/db: let ChannelGraph init the graphCache
In this commit, we let the ChannelGraph be responsible for populating the graphCache and then passing it to the KVStore. This is a first step in moving the graphCache completely out of the KVStore layer.
This commit is contained in:
8 files changed
+129
-80
No files matched your search
+6
-3
@@ -1030,14 +1030,17 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
|||||||
graphdb.WithRejectCacheSize(cfg.Caches.RejectCacheSize),
|
graphdb.WithRejectCacheSize(cfg.Caches.RejectCacheSize),
|
||||||
graphdb.WithChannelCacheSize(cfg.Caches.ChannelCacheSize),
|
graphdb.WithChannelCacheSize(cfg.Caches.ChannelCacheSize),
|
||||||
graphdb.WithBatchCommitInterval(cfg.DB.BatchCommitInterval),
|
graphdb.WithBatchCommitInterval(cfg.DB.BatchCommitInterval),
|
||||||
|
}
|
||||||
|
|
||||||
|
chanGraphOpts := []graphdb.ChanGraphOption{
|
||||||
graphdb.WithUseGraphCache(!cfg.DB.NoGraphCache),
|
graphdb.WithUseGraphCache(!cfg.DB.NoGraphCache),
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to pre-allocate the channel graph cache according to what we
|
// We want to pre-allocate the channel graph cache according to what we
|
||||||
// expect for mainnet to speed up memory allocation.
|
// expect for mainnet to speed up memory allocation.
|
||||||
if cfg.ActiveNetParams.Name == chaincfg.MainNetParams.Name {
|
if cfg.ActiveNetParams.Name == chaincfg.MainNetParams.Name {
|
||||||
graphDBOptions = append(
|
chanGraphOpts = append(
|
||||||
graphDBOptions, graphdb.WithPreAllocCacheNumNodes(
|
chanGraphOpts, graphdb.WithPreAllocCacheNumNodes(
|
||||||
graphdb.DefaultPreAllocCacheNumNodes,
|
graphdb.DefaultPreAllocCacheNumNodes,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1046,7 +1049,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
|||||||
dbs.GraphDB, err = graphdb.NewChannelGraph(&graphdb.Config{
|
dbs.GraphDB, err = graphdb.NewChannelGraph(&graphdb.Config{
|
||||||
KVDB: databaseBackends.GraphDB,
|
KVDB: databaseBackends.GraphDB,
|
||||||
KVStoreOpts: graphDBOptions,
|
KVStoreOpts: graphDBOptions,
|
||||||
})
|
}, chanGraphOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanUp()
|
cleanUp()
|
||||||
|
|
||||||
|
|||||||
@@ -323,6 +323,7 @@ The underlying functionality between those two options remain the same.
|
|||||||
- [Refactor to hide DB transactions](https://github.com/lightningnetwork/lnd/pull/9513)
|
- [Refactor to hide DB transactions](https://github.com/lightningnetwork/lnd/pull/9513)
|
||||||
- Move the graph cache out of the graph CRUD layer:
|
- Move the graph cache out of the graph CRUD layer:
|
||||||
- [1](https://github.com/lightningnetwork/lnd/pull/9533)
|
- [1](https://github.com/lightningnetwork/lnd/pull/9533)
|
||||||
|
- [2](https://github.com/lightningnetwork/lnd/pull/9545)
|
||||||
|
|
||||||
* [Golang was updated to
|
* [Golang was updated to
|
||||||
`v1.22.11`](https://github.com/lightningnetwork/lnd/pull/9462).
|
`v1.22.11`](https://github.com/lightningnetwork/lnd/pull/9462).
|
||||||
|
|||||||
+60
-3
@@ -1,6 +1,13 @@
|
|||||||
package graphdb
|
package graphdb
|
||||||
|
|
||||||
import "github.com/lightningnetwork/lnd/kvdb"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||||
|
"github.com/lightningnetwork/lnd/kvdb"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
|
)
|
||||||
|
|
||||||
// Config is a struct that holds all the necessary dependencies for a
|
// Config is a struct that holds all the necessary dependencies for a
|
||||||
// ChannelGraph.
|
// ChannelGraph.
|
||||||
@@ -20,17 +27,67 @@ type Config struct {
|
|||||||
// KVStore. Upcoming commits will move the graph cache out of the KVStore and
|
// KVStore. Upcoming commits will move the graph cache out of the KVStore and
|
||||||
// into this layer so that the KVStore is only responsible for CRUD operations.
|
// into this layer so that the KVStore is only responsible for CRUD operations.
|
||||||
type ChannelGraph struct {
|
type ChannelGraph struct {
|
||||||
|
graphCache *GraphCache
|
||||||
|
|
||||||
*KVStore
|
*KVStore
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChannelGraph creates a new ChannelGraph instance with the given backend.
|
// NewChannelGraph creates a new ChannelGraph instance with the given backend.
|
||||||
func NewChannelGraph(cfg *Config) (*ChannelGraph, error) {
|
func NewChannelGraph(cfg *Config, options ...ChanGraphOption) (*ChannelGraph,
|
||||||
|
error) {
|
||||||
|
|
||||||
|
opts := defaultChanGraphOptions()
|
||||||
|
for _, o := range options {
|
||||||
|
o(opts)
|
||||||
|
}
|
||||||
|
|
||||||
store, err := NewKVStore(cfg.KVDB, cfg.KVStoreOpts...)
|
store, err := NewKVStore(cfg.KVDB, cfg.KVStoreOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !opts.useGraphCache {
|
||||||
|
return &ChannelGraph{
|
||||||
|
KVStore: store,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The graph cache can be turned off (e.g. for mobile users) for a
|
||||||
|
// speed/memory usage tradeoff.
|
||||||
|
graphCache := NewGraphCache(opts.preAllocCacheNumNodes)
|
||||||
|
startTime := time.Now()
|
||||||
|
log.Debugf("Populating in-memory channel graph, this might take a " +
|
||||||
|
"while...")
|
||||||
|
|
||||||
|
err = store.ForEachNodeCacheable(func(node route.Vertex,
|
||||||
|
features *lnwire.FeatureVector) error {
|
||||||
|
|
||||||
|
graphCache.AddNodeFeatures(node, features)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.ForEachChannel(func(info *models.ChannelEdgeInfo,
|
||||||
|
policy1, policy2 *models.ChannelEdgePolicy) error {
|
||||||
|
|
||||||
|
graphCache.AddChannel(info, policy1, policy2)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Finished populating in-memory channel graph (took %v, %s)",
|
||||||
|
time.Since(startTime), graphCache.Stats())
|
||||||
|
|
||||||
|
store.setGraphCache(graphCache)
|
||||||
|
|
||||||
return &ChannelGraph{
|
return &ChannelGraph{
|
||||||
KVStore: store,
|
KVStore: store,
|
||||||
|
graphCache: graphCache,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -3924,6 +3924,7 @@ func TestGraphCacheForEachNodeChannel(t *testing.T) {
|
|||||||
// Unset the channel graph cache to simulate the user running with the
|
// Unset the channel graph cache to simulate the user running with the
|
||||||
// option turned off.
|
// option turned off.
|
||||||
graph.graphCache = nil
|
graph.graphCache = nil
|
||||||
|
graph.KVStore.graphCache = nil
|
||||||
|
|
||||||
node1, err := createTestVertex(graph.db)
|
node1, err := createTestVertex(graph.db)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|||||||
+9
-34
@@ -224,43 +224,18 @@ func NewKVStore(db kvdb.Backend, options ...KVStoreOptionModifier) (*KVStore,
|
|||||||
db, nil, opts.BatchCommitInterval,
|
db, nil, opts.BatchCommitInterval,
|
||||||
)
|
)
|
||||||
|
|
||||||
// The graph cache can be turned off (e.g. for mobile users) for a
|
|
||||||
// speed/memory usage tradeoff.
|
|
||||||
if opts.UseGraphCache {
|
|
||||||
g.graphCache = NewGraphCache(opts.PreAllocCacheNumNodes)
|
|
||||||
startTime := time.Now()
|
|
||||||
log.Debugf("Populating in-memory channel graph, this might " +
|
|
||||||
"take a while...")
|
|
||||||
|
|
||||||
err := g.ForEachNodeCacheable(func(node route.Vertex,
|
|
||||||
features *lnwire.FeatureVector) error {
|
|
||||||
|
|
||||||
g.graphCache.AddNodeFeatures(node, features)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = g.ForEachChannel(func(info *models.ChannelEdgeInfo,
|
|
||||||
policy1, policy2 *models.ChannelEdgePolicy) error {
|
|
||||||
|
|
||||||
g.graphCache.AddChannel(info, policy1, policy2)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Finished populating in-memory channel graph (took "+
|
|
||||||
"%v, %s)", time.Since(startTime), g.graphCache.Stats())
|
|
||||||
}
|
|
||||||
|
|
||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setGraphCache sets the KVStore's graphCache.
|
||||||
|
//
|
||||||
|
// NOTE: this is temporary and will only be called from the ChannelGraph's
|
||||||
|
// constructor before the KVStore methods are available to be called. This will
|
||||||
|
// be removed once the graph cache is fully owned by the ChannelGraph.
|
||||||
|
func (c *KVStore) setGraphCache(cache *GraphCache) {
|
||||||
|
c.graphCache = cache
|
||||||
|
}
|
||||||
|
|
||||||
// channelMapKey is the key structure used for storing channel edge policies.
|
// channelMapKey is the key structure used for storing channel edge policies.
|
||||||
type channelMapKey struct {
|
type channelMapKey struct {
|
||||||
nodeKey route.Vertex
|
nodeKey route.Vertex
|
||||||
|
|||||||
+44
-28
@@ -20,6 +20,47 @@ const (
|
|||||||
DefaultPreAllocCacheNumNodes = 15000
|
DefaultPreAllocCacheNumNodes = 15000
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// chanGraphOptions holds parameters for tuning and customizing the
|
||||||
|
// ChannelGraph.
|
||||||
|
type chanGraphOptions struct {
|
||||||
|
// useGraphCache denotes whether the in-memory graph cache should be
|
||||||
|
// used or a fallback version that uses the underlying database for
|
||||||
|
// path finding.
|
||||||
|
useGraphCache bool
|
||||||
|
|
||||||
|
// preAllocCacheNumNodes is the number of nodes we expect to be in the
|
||||||
|
// graph cache, so we can pre-allocate the map accordingly.
|
||||||
|
preAllocCacheNumNodes int
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultChanGraphOptions returns a new chanGraphOptions instance populated
|
||||||
|
// with default values.
|
||||||
|
func defaultChanGraphOptions() *chanGraphOptions {
|
||||||
|
return &chanGraphOptions{
|
||||||
|
useGraphCache: true,
|
||||||
|
preAllocCacheNumNodes: DefaultPreAllocCacheNumNodes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChanGraphOption describes the signature of a functional option that can be
|
||||||
|
// used to customize a ChannelGraph instance.
|
||||||
|
type ChanGraphOption func(*chanGraphOptions)
|
||||||
|
|
||||||
|
// WithUseGraphCache sets whether the in-memory graph cache should be used.
|
||||||
|
func WithUseGraphCache(use bool) ChanGraphOption {
|
||||||
|
return func(o *chanGraphOptions) {
|
||||||
|
o.useGraphCache = use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPreAllocCacheNumNodes sets the number of nodes we expect to be in the
|
||||||
|
// graph cache, so we can pre-allocate the map accordingly.
|
||||||
|
func WithPreAllocCacheNumNodes(n int) ChanGraphOption {
|
||||||
|
return func(o *chanGraphOptions) {
|
||||||
|
o.preAllocCacheNumNodes = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// KVStoreOptions holds parameters for tuning and customizing a graph.DB.
|
// KVStoreOptions holds parameters for tuning and customizing a graph.DB.
|
||||||
type KVStoreOptions struct {
|
type KVStoreOptions struct {
|
||||||
// RejectCacheSize is the maximum number of rejectCacheEntries to hold
|
// RejectCacheSize is the maximum number of rejectCacheEntries to hold
|
||||||
@@ -34,15 +75,6 @@ type KVStoreOptions struct {
|
|||||||
// wait before attempting to commit a pending set of updates.
|
// wait before attempting to commit a pending set of updates.
|
||||||
BatchCommitInterval time.Duration
|
BatchCommitInterval time.Duration
|
||||||
|
|
||||||
// PreAllocCacheNumNodes is the number of nodes we expect to be in the
|
|
||||||
// graph cache, so we can pre-allocate the map accordingly.
|
|
||||||
PreAllocCacheNumNodes int
|
|
||||||
|
|
||||||
// UseGraphCache denotes whether the in-memory graph cache should be
|
|
||||||
// used or a fallback version that uses the underlying database for
|
|
||||||
// path finding.
|
|
||||||
UseGraphCache bool
|
|
||||||
|
|
||||||
// NoMigration specifies that underlying backend was opened in read-only
|
// NoMigration specifies that underlying backend was opened in read-only
|
||||||
// mode and migrations shouldn't be performed. This can be useful for
|
// mode and migrations shouldn't be performed. This can be useful for
|
||||||
// applications that use the channeldb package as a library.
|
// applications that use the channeldb package as a library.
|
||||||
@@ -52,11 +84,9 @@ type KVStoreOptions struct {
|
|||||||
// DefaultOptions returns a KVStoreOptions populated with default values.
|
// DefaultOptions returns a KVStoreOptions populated with default values.
|
||||||
func DefaultOptions() *KVStoreOptions {
|
func DefaultOptions() *KVStoreOptions {
|
||||||
return &KVStoreOptions{
|
return &KVStoreOptions{
|
||||||
RejectCacheSize: DefaultRejectCacheSize,
|
RejectCacheSize: DefaultRejectCacheSize,
|
||||||
ChannelCacheSize: DefaultChannelCacheSize,
|
ChannelCacheSize: DefaultChannelCacheSize,
|
||||||
PreAllocCacheNumNodes: DefaultPreAllocCacheNumNodes,
|
NoMigration: false,
|
||||||
UseGraphCache: true,
|
|
||||||
NoMigration: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,13 +108,6 @@ func WithChannelCacheSize(n int) KVStoreOptionModifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithPreAllocCacheNumNodes sets the PreAllocCacheNumNodes to n.
|
|
||||||
func WithPreAllocCacheNumNodes(n int) KVStoreOptionModifier {
|
|
||||||
return func(o *KVStoreOptions) {
|
|
||||||
o.PreAllocCacheNumNodes = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithBatchCommitInterval sets the batch commit interval for the interval batch
|
// WithBatchCommitInterval sets the batch commit interval for the interval batch
|
||||||
// schedulers.
|
// schedulers.
|
||||||
func WithBatchCommitInterval(interval time.Duration) KVStoreOptionModifier {
|
func WithBatchCommitInterval(interval time.Duration) KVStoreOptionModifier {
|
||||||
@@ -92,10 +115,3 @@ func WithBatchCommitInterval(interval time.Duration) KVStoreOptionModifier {
|
|||||||
o.BatchCommitInterval = interval
|
o.BatchCommitInterval = interval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithUseGraphCache sets the UseGraphCache option to the given value.
|
|
||||||
func WithUseGraphCache(use bool) KVStoreOptionModifier {
|
|
||||||
return func(o *KVStoreOptions) {
|
|
||||||
o.UseGraphCache = use
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1093,12 +1093,10 @@ func makeTestGraph(t *testing.T, useCache bool) (*graphdb.ChannelGraph,
|
|||||||
|
|
||||||
t.Cleanup(backendCleanup)
|
t.Cleanup(backendCleanup)
|
||||||
|
|
||||||
graph, err := graphdb.NewChannelGraph(&graphdb.Config{
|
graph, err := graphdb.NewChannelGraph(
|
||||||
KVDB: backend,
|
&graphdb.Config{KVDB: backend},
|
||||||
KVStoreOpts: []graphdb.KVStoreOptionModifier{
|
graphdb.WithUseGraphCache(useCache),
|
||||||
graphdb.WithUseGraphCache(useCache),
|
)
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,12 +166,10 @@ func makeTestGraph(t *testing.T, useCache bool) (*graphdb.ChannelGraph,
|
|||||||
|
|
||||||
t.Cleanup(backendCleanup)
|
t.Cleanup(backendCleanup)
|
||||||
|
|
||||||
graph, err := graphdb.NewChannelGraph(&graphdb.Config{
|
graph, err := graphdb.NewChannelGraph(
|
||||||
KVDB: backend,
|
&graphdb.Config{KVDB: backend},
|
||||||
KVStoreOpts: []graphdb.KVStoreOptionModifier{
|
graphdb.WithUseGraphCache(useCache),
|
||||||
graphdb.WithUseGraphCache(useCache),
|
)
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user