Skip to content

Commit 5344f5d

Browse files
committed
blockservice & exchange & bitswap: add non variadic NotifyNewBlock
Variadicts in go are just syntactic sugar around passing a slice, that means all go memory reachability rules apply, this force the compiler to heap allocate the variadic slice for virtual call, because the implementation is allowed to leak the slice (and go's interprocedural optimisations do not cover escape). Passing a block without variadic will pass the itab either on the stack or decomposed through registers. Skipping having to allocate a slice.
1 parent 6f324be commit 5344f5d

File tree

7 files changed

+46
-7
lines changed

7 files changed

+46
-7
lines changed

bitswap/bitswap.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ func New(ctx context.Context, net network.BitSwapNetwork, bstore blockstore.Bloc
9696
return bs
9797
}
9898

99+
func (bs *Bitswap) NotifyNewBlock(ctx context.Context, blk blocks.Block) error {
100+
return multierr.Combine(
101+
bs.Client.NotifyNewBlock(ctx, blk),
102+
bs.Server.NotifyNewBlock(ctx, blk),
103+
)
104+
}
105+
99106
func (bs *Bitswap) NotifyNewBlocks(ctx context.Context, blks ...blocks.Block) error {
100107
return multierr.Combine(
101108
bs.Client.NotifyNewBlocks(ctx, blks...),

bitswap/client/client.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ func (bs *Client) GetBlocks(ctx context.Context, keys []cid.Cid) (<-chan blocks.
259259
return session.GetBlocks(ctx, keys)
260260
}
261261

262+
// NotifyNewBlock announces the existence of blocks to this bitswap service.
263+
// Bitswap itself doesn't store new blocks. It's the caller responsibility to ensure
264+
// that those blocks are available in the blockstore before calling this function.
265+
func (bs *Client) NotifyNewBlock(ctx context.Context, blk blocks.Block) error {
266+
// Call to the variadic to avoid code duplication.
267+
// This is actually fine to do because no calls is virtual the compiler is able
268+
// to see that the slice does not leak and the slice is stack allocated.
269+
return bs.NotifyNewBlocks(ctx, blk)
270+
}
271+
262272
// NotifyNewBlocks announces the existence of blocks to this bitswap service.
263273
// Bitswap itself doesn't store new blocks. It's the caller responsibility to ensure
264274
// that those blocks are available in the blockstore before calling this function.

bitswap/server/server.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,17 @@ func (bs *Server) Stat() (Stat, error) {
404404
return s, nil
405405
}
406406

407+
// NotifyNewBlock announces the existence of block to this bitswap service. The
408+
// service will potentially notify its peers.
409+
// Bitswap itself doesn't store new blocks. It's the caller responsibility to ensure
410+
// that those blocks are available in the blockstore before calling this function.
411+
func (bs *Server) NotifyNewBlock(ctx context.Context, blk blocks.Block) error {
412+
// Call to the variadic to avoid code duplication.
413+
// This is actually fine to do because no calls is virtual the compiler is able
414+
// to see that the slice does not leak and the slice is stack allocated.
415+
return bs.NotifyNewBlocks(ctx, blk)
416+
}
417+
407418
// NotifyNewBlocks announces the existence of blocks to this bitswap service. The
408419
// service will potentially notify its peers.
409420
// Bitswap itself doesn't store new blocks. It's the caller responsibility to ensure

blockservice/blockservice.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ func (s *blockService) AddBlock(ctx context.Context, o blocks.Block) error {
157157
logger.Debugf("BlockService.BlockAdded %s", c)
158158

159159
if s.exchange != nil {
160-
if err := s.exchange.NotifyNewBlocks(ctx, o); err != nil {
161-
logger.Errorf("NotifyNewBlocks: %s", err.Error())
160+
if err := s.exchange.NotifyNewBlock(ctx, o); err != nil {
161+
logger.Errorf("NotifyNewBlock: %s", err.Error())
162162
}
163163
}
164164

@@ -254,7 +254,7 @@ func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, fget fun
254254
if err != nil {
255255
return nil, err
256256
}
257-
err = f.NotifyNewBlocks(ctx, blk)
257+
err = f.NotifyNewBlock(ctx, blk)
258258
if err != nil {
259259
return nil, err
260260
}
@@ -334,7 +334,6 @@ func getBlocks(ctx context.Context, ks []cid.Cid, bs blockstore.Blockstore, fget
334334
return
335335
}
336336

337-
var cache [1]blocks.Block // preallocate once for all iterations
338337
for {
339338
var b blocks.Block
340339
select {
@@ -355,13 +354,11 @@ func getBlocks(ctx context.Context, ks []cid.Cid, bs blockstore.Blockstore, fget
355354
}
356355

357356
// inform the exchange that the blocks are available
358-
cache[0] = b
359-
err = f.NotifyNewBlocks(ctx, cache[:]...)
357+
err = f.NotifyNewBlock(ctx, b)
360358
if err != nil {
361359
logger.Errorf("could not tell the exchange about new blocks: %s", err)
362360
return
363361
}
364-
cache[0] = nil // early gc
365362

366363
select {
367364
case out <- b:
@@ -391,6 +388,7 @@ func (s *blockService) Close() error {
391388
}
392389

393390
type notifier interface {
391+
NotifyNewBlock(context.Context, blocks.Block) error
394392
NotifyNewBlocks(context.Context, ...blocks.Block) error
395393
}
396394

blockservice/blockservice_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ type notifyCountingExchange struct {
195195
notifyCount int
196196
}
197197

198+
func (n *notifyCountingExchange) NotifyNewBlock(ctx context.Context, blocks blocks.Block) error {
199+
n.notifyCount++
200+
return n.Interface.NotifyNewBlock(ctx, blocks)
201+
}
202+
198203
func (n *notifyCountingExchange) NotifyNewBlocks(ctx context.Context, blocks ...blocks.Block) error {
199204
n.notifyCount += len(blocks)
200205
return n.Interface.NotifyNewBlocks(ctx, blocks...)

exchange/interface.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
type Interface interface { // type Exchanger interface
1414
Fetcher
1515

16+
// NotifyNewBlock tells the exchange that a new block is available and can be served.
17+
NotifyNewBlock(ctx context.Context, blocks blocks.Block) error
1618
// NotifyNewBlocks tells the exchange that new blocks are available and can be served.
1719
NotifyNewBlocks(ctx context.Context, blocks ...blocks.Block) error
1820

exchange/offline/offline.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ func (e *offlineExchange) GetBlock(ctx context.Context, k cid.Cid) (blocks.Block
3434
return blk, err
3535
}
3636

37+
// NotifyNewBlock tells the exchange that a new block is available and can be served.
38+
func (e *offlineExchange) NotifyNewBlock(ctx context.Context, block blocks.Block) error {
39+
// as an offline exchange we have nothing to do
40+
return nil
41+
}
42+
3743
// NotifyNewBlocks tells the exchange that new blocks are available and can be served.
3844
func (e *offlineExchange) NotifyNewBlocks(ctx context.Context, blocks ...blocks.Block) error {
3945
// as an offline exchange we have nothing to do

0 commit comments

Comments
 (0)