Skip to content
This repository was archived by the owner on Feb 1, 2023. It is now read-only.

Commit 47b99b1

Browse files
authored
feat: configurable engine blockstore worker count (#449)
1 parent 95cb1a0 commit 47b99b1

File tree

5 files changed

+56
-42
lines changed

5 files changed

+56
-42
lines changed

bitswap.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package bitswap
55
import (
66
"context"
77
"errors"
8+
"fmt"
89

910
"sync"
1011
"time"
@@ -45,6 +46,9 @@ const (
4546
// these requests take at _least_ two minutes at the moment.
4647
provideTimeout = time.Minute * 3
4748
defaultProvSearchDelay = time.Second
49+
50+
// Number of concurrent workers in decision engine that process requests to the blockstore
51+
defaulEngineBlockstoreWorkerCount = 128
4852
)
4953

5054
var (
@@ -85,6 +89,17 @@ func RebroadcastDelay(newRebroadcastDelay delay.D) Option {
8589
}
8690
}
8791

92+
// EngineBlockstoreWorkerCount sets the number of worker threads used for
93+
// blockstore operations in the decision engine
94+
func EngineBlockstoreWorkerCount(count int) Option {
95+
if count <= 0 {
96+
panic(fmt.Sprintf("Engine blockstore worker count is %d but must be > 0", count))
97+
}
98+
return func(bs *Bitswap) {
99+
bs.engineBstoreWorkerCount = count
100+
}
101+
}
102+
88103
// SetSendDontHaves indicates what to do when the engine receives a want-block
89104
// for a block that is not in the blockstore. Either
90105
// - Send a DONT_HAVE message
@@ -99,7 +114,7 @@ func SetSendDontHaves(send bool) Option {
99114
// Configures the engine to use the given score decision logic.
100115
func WithScoreLedger(scoreLedger deciface.ScoreLedger) Option {
101116
return func(bs *Bitswap) {
102-
bs.engine.UseScoreLedger(scoreLedger)
117+
bs.engineScoreLedger = scoreLedger
103118
}
104119
}
105120

@@ -166,40 +181,42 @@ func New(parent context.Context, network bsnet.BitSwapNetwork,
166181
}
167182
notif := notifications.New()
168183
sm = bssm.New(ctx, sessionFactory, sim, sessionPeerManagerFactory, bpm, pm, notif, network.Self())
169-
engine := decision.NewEngine(ctx, bstore, network.ConnectionManager(), network.Self())
170184

171185
bs := &Bitswap{
172186
blockstore: bstore,
173-
engine: engine,
174187
network: network,
175188
process: px,
176189
newBlocks: make(chan cid.Cid, HasBlockBufferSize),
177190
provideKeys: make(chan cid.Cid, provideKeysBufferSize),
178191
pm: pm,
179192
pqm: pqm,
180-
sm: sm,
181-
sim: sim,
182-
notif: notif,
183-
counters: new(counters),
184-
dupMetric: dupHist,
185-
allMetric: allHist,
186-
sentHistogram: sentHistogram,
187-
provideEnabled: true,
188-
provSearchDelay: defaultProvSearchDelay,
189-
rebroadcastDelay: delay.Fixed(time.Minute),
193+
sm: sm,
194+
sim: sim,
195+
notif: notif,
196+
counters: new(counters),
197+
dupMetric: dupHist,
198+
allMetric: allHist,
199+
sentHistogram: sentHistogram,
200+
provideEnabled: true,
201+
provSearchDelay: defaultProvSearchDelay,
202+
rebroadcastDelay: delay.Fixed(time.Minute),
203+
engineBstoreWorkerCount: defaulEngineBlockstoreWorkerCount,
190204
}
191205

192206
// apply functional options before starting and running bitswap
193207
for _, option := range options {
194208
option(bs)
195209
}
196210

211+
// Set up decision engine
212+
bs.engine = decision.NewEngine(bstore, bs.engineBstoreWorkerCount, network.ConnectionManager(), network.Self(), bs.engineScoreLedger)
213+
197214
bs.pqm.Startup()
198215
network.SetDelegate(bs)
199216

200217
// Start up bitswaps async worker routines
201218
bs.startWorkers(ctx, px)
202-
engine.StartWorkers(ctx, px)
219+
bs.engine.StartWorkers(ctx, px)
203220

204221
// bind the context and process.
205222
// do it over here to avoid closing before all setup is done.
@@ -270,6 +287,12 @@ type Bitswap struct {
270287

271288
// how often to rebroadcast providing requests to find more optimized providers
272289
rebroadcastDelay delay.D
290+
291+
// how many worker threads to start for decision engine blockstore worker
292+
engineBstoreWorkerCount int
293+
294+
// the score ledger used by the decision engine
295+
engineScoreLedger deciface.ScoreLedger
273296
}
274297

275298
type counters struct {

internal/decision/blockstoremanager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type blockstoreManager struct {
2121

2222
// newBlockstoreManager creates a new blockstoreManager with the given context
2323
// and number of workers
24-
func newBlockstoreManager(ctx context.Context, bs bstore.Blockstore, workerCount int) *blockstoreManager {
24+
func newBlockstoreManager(bs bstore.Blockstore, workerCount int) *blockstoreManager {
2525
return &blockstoreManager{
2626
bs: bs,
2727
workerCount: workerCount,

internal/decision/blockstoremanager_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestBlockstoreManagerNotFoundKey(t *testing.T) {
2525
dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay))
2626
bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore))
2727

28-
bsm := newBlockstoreManager(ctx, bstore, 5)
28+
bsm := newBlockstoreManager(bstore, 5)
2929
bsm.start(process.WithTeardown(func() error { return nil }))
3030

3131
cids := testutil.GenerateCids(4)
@@ -64,7 +64,7 @@ func TestBlockstoreManager(t *testing.T) {
6464
dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay))
6565
bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore))
6666

67-
bsm := newBlockstoreManager(ctx, bstore, 5)
67+
bsm := newBlockstoreManager(bstore, 5)
6868
bsm.start(process.WithTeardown(func() error { return nil }))
6969

7070
exp := make(map[cid.Cid]blocks.Block)
@@ -148,7 +148,7 @@ func TestBlockstoreManagerConcurrency(t *testing.T) {
148148
bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore))
149149

150150
workerCount := 5
151-
bsm := newBlockstoreManager(ctx, bstore, workerCount)
151+
bsm := newBlockstoreManager(bstore, workerCount)
152152
bsm.start(process.WithTeardown(func() error { return nil }))
153153

154154
blkSize := int64(8 * 1024)
@@ -190,7 +190,7 @@ func TestBlockstoreManagerClose(t *testing.T) {
190190
dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay))
191191
bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore))
192192

193-
bsm := newBlockstoreManager(ctx, bstore, 3)
193+
bsm := newBlockstoreManager(bstore, 3)
194194
px := process.WithTeardown(func() error { return nil })
195195
bsm.start(px)
196196

@@ -227,7 +227,7 @@ func TestBlockstoreManagerCtxDone(t *testing.T) {
227227
dstore := ds_sync.MutexWrap(delayed.New(ds.NewMapDatastore(), bsdelay))
228228
bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(dstore))
229229

230-
bsm := newBlockstoreManager(context.Background(), bstore, 3)
230+
bsm := newBlockstoreManager(bstore, 3)
231231
proc := process.WithTeardown(func() error { return nil })
232232
bsm.start(proc)
233233

internal/decision/engine.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ const (
7676

7777
// Number of concurrent workers that pull tasks off the request queue
7878
taskWorkerCount = 8
79-
80-
// Number of concurrent workers that process requests to the blockstore
81-
blockstoreWorkerCount = 128
8279
)
8380

8481
// Envelope contains a message for a Peer.
@@ -166,16 +163,16 @@ type Engine struct {
166163

167164
sendDontHaves bool
168165

169-
self peer.ID
166+
self peer.ID
170167
}
171168

172169
// NewEngine creates a new block sending engine for the given block store
173-
func NewEngine(ctx context.Context, bs bstore.Blockstore, peerTagger PeerTagger, self peer.ID) *Engine {
174-
return newEngine(ctx, bs, peerTagger, self, maxBlockSizeReplaceHasWithBlock, nil)
170+
func NewEngine(bs bstore.Blockstore, bstoreWorkerCount int, peerTagger PeerTagger, self peer.ID, scoreLedger ScoreLedger) *Engine {
171+
return newEngine(bs, bstoreWorkerCount, peerTagger, self, maxBlockSizeReplaceHasWithBlock, scoreLedger)
175172
}
176173

177174
// This constructor is used by the tests
178-
func newEngine(ctx context.Context, bs bstore.Blockstore, peerTagger PeerTagger, self peer.ID,
175+
func newEngine(bs bstore.Blockstore, bstoreWorkerCount int, peerTagger PeerTagger, self peer.ID,
179176
maxReplaceSize int, scoreLedger ScoreLedger) *Engine {
180177

181178
if scoreLedger == nil {
@@ -185,7 +182,7 @@ func newEngine(ctx context.Context, bs bstore.Blockstore, peerTagger PeerTagger,
185182
e := &Engine{
186183
ledgerMap: make(map[peer.ID]*ledger),
187184
scoreLedger: scoreLedger,
188-
bsm: newBlockstoreManager(ctx, bs, blockstoreWorkerCount),
185+
bsm: newBlockstoreManager(bs, bstoreWorkerCount),
189186
peerTagger: peerTagger,
190187
outbox: make(chan (<-chan *Envelope), outboxChanBuffer),
191188
workSignal: make(chan struct{}, 1),
@@ -215,12 +212,6 @@ func (e *Engine) SetSendDontHaves(send bool) {
215212
e.sendDontHaves = send
216213
}
217214

218-
// Sets the scoreLedger to the given implementation. Should be called
219-
// before StartWorkers().
220-
func (e *Engine) UseScoreLedger(scoreLedger ScoreLedger) {
221-
e.scoreLedger = scoreLedger
222-
}
223-
224215
// Starts the score ledger. Before start the function checks and,
225216
// if it is unset, initializes the scoreLedger with the default
226217
// implementation.

internal/decision/engine_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func newTestEngine(ctx context.Context, idStr string) engineSet {
9797
func newTestEngineWithSampling(ctx context.Context, idStr string, peerSampleInterval time.Duration, sampleCh chan struct{}) engineSet {
9898
fpt := &fakePeerTagger{}
9999
bs := blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore()))
100-
e := newEngine(ctx, bs, fpt, "localhost", 0, NewTestScoreLedger(peerSampleInterval, sampleCh))
100+
e := newEngine(bs, 4, fpt, "localhost", 0, NewTestScoreLedger(peerSampleInterval, sampleCh))
101101
e.StartWorkers(ctx, process.WithTeardown(func() error { return nil }))
102102
return engineSet{
103103
Peer: peer.ID(idStr),
@@ -185,7 +185,7 @@ func peerIsPartner(p peer.ID, e *Engine) bool {
185185
func TestOutboxClosedWhenEngineClosed(t *testing.T) {
186186
ctx := context.Background()
187187
t.SkipNow() // TODO implement *Engine.Close
188-
e := newEngine(ctx, blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())), &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
188+
e := newEngine(blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())), 4, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
189189
e.StartWorkers(ctx, process.WithTeardown(func() error { return nil }))
190190
var wg sync.WaitGroup
191191
wg.Add(1)
@@ -513,7 +513,7 @@ func TestPartnerWantHaveWantBlockNonActive(t *testing.T) {
513513
testCases = onlyTestCases
514514
}
515515

516-
e := newEngine(context.Background(), bs, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
516+
e := newEngine(bs, 4, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
517517
e.StartWorkers(context.Background(), process.WithTeardown(func() error { return nil }))
518518
for i, testCase := range testCases {
519519
t.Logf("Test case %d:", i)
@@ -669,7 +669,7 @@ func TestPartnerWantHaveWantBlockActive(t *testing.T) {
669669
testCases = onlyTestCases
670670
}
671671

672-
e := newEngine(context.Background(), bs, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
672+
e := newEngine(bs, 4, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
673673
e.StartWorkers(context.Background(), process.WithTeardown(func() error { return nil }))
674674

675675
var next envChan
@@ -854,7 +854,7 @@ func TestPartnerWantsThenCancels(t *testing.T) {
854854
ctx := context.Background()
855855
for i := 0; i < numRounds; i++ {
856856
expected := make([][]string, 0, len(testcases))
857-
e := newEngine(ctx, bs, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
857+
e := newEngine(bs, 4, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
858858
e.StartWorkers(ctx, process.WithTeardown(func() error { return nil }))
859859
for _, testcase := range testcases {
860860
set := testcase[0]
@@ -879,7 +879,7 @@ func TestSendReceivedBlocksToPeersThatWantThem(t *testing.T) {
879879
partner := libp2ptest.RandPeerIDFatal(t)
880880
otherPeer := libp2ptest.RandPeerIDFatal(t)
881881

882-
e := newEngine(context.Background(), bs, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
882+
e := newEngine(bs, 4, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
883883
e.StartWorkers(context.Background(), process.WithTeardown(func() error { return nil }))
884884

885885
blks := testutil.GenerateBlocksOfSize(4, 8*1024)
@@ -923,7 +923,7 @@ func TestSendDontHave(t *testing.T) {
923923
partner := libp2ptest.RandPeerIDFatal(t)
924924
otherPeer := libp2ptest.RandPeerIDFatal(t)
925925

926-
e := newEngine(context.Background(), bs, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
926+
e := newEngine(bs, 4, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
927927
e.StartWorkers(context.Background(), process.WithTeardown(func() error { return nil }))
928928

929929
blks := testutil.GenerateBlocksOfSize(4, 8*1024)
@@ -987,7 +987,7 @@ func TestWantlistForPeer(t *testing.T) {
987987
partner := libp2ptest.RandPeerIDFatal(t)
988988
otherPeer := libp2ptest.RandPeerIDFatal(t)
989989

990-
e := newEngine(context.Background(), bs, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
990+
e := newEngine(bs, 4, &fakePeerTagger{}, "localhost", 0, NewTestScoreLedger(shortTerm, nil))
991991
e.StartWorkers(context.Background(), process.WithTeardown(func() error { return nil }))
992992

993993
blks := testutil.GenerateBlocksOfSize(4, 8*1024)

0 commit comments

Comments
 (0)