80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
|
package lnpeer
|
||
|
|
||
|
import (
|
||
|
"time"
|
||
|
|
||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||
|
"github.com/lightningnetwork/lnd/queue"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// DefaultGCInterval is the default interval that the WriteBufferPool
|
||
|
// will perform a sweep to see which expired buffers can be released to
|
||
|
// the runtime.
|
||
|
DefaultGCInterval = 15 * time.Second
|
||
|
|
||
|
// DefaultExpiryInterval is the default, minimum interval that must
|
||
|
// elapse before a WriteBuffer will be released. The maximum time before
|
||
|
// the buffer can be released is equal to the expiry interval plus the
|
||
|
// gc interval.
|
||
|
DefaultExpiryInterval = 30 * time.Second
|
||
|
)
|
||
|
|
||
|
// WriteBuffer is static byte array occupying to maximum-allowed
|
||
|
// plaintext-message size.
|
||
|
type WriteBuffer [lnwire.MaxMessagePayload]byte
|
||
|
|
||
|
// Recycle zeroes the WriteBuffer, making it fresh for another use.
|
||
|
// Zeroing the buffer using a logarithmic number of calls to the optimized copy
|
||
|
// method. Benchmarking shows this to be ~30 times faster than a for loop that
|
||
|
// sets each index to 0 for this buffer size. Inspired by:
|
||
|
// https://stackoverflow.com/questions/30614165/is-there-analog-of-memset-in-go
|
||
|
//
|
||
|
// This is part of the queue.Recycler interface.
|
||
|
func (b *WriteBuffer) Recycle() {
|
||
|
b[0] = 0
|
||
|
for i := 1; i < lnwire.MaxMessagePayload; i *= 2 {
|
||
|
copy(b[i:], b[:i])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// newRecyclableWriteBuffer is a constructor that returns a WriteBuffer typed as
|
||
|
// a queue.Recycler.
|
||
|
func newRecyclableWriteBuffer() queue.Recycler {
|
||
|
return new(WriteBuffer)
|
||
|
}
|
||
|
|
||
|
// A compile-time constraint to ensure that *WriteBuffer implements the
|
||
|
// queue.Recycler interface.
|
||
|
var _ queue.Recycler = (*WriteBuffer)(nil)
|
||
|
|
||
|
// WriteBufferPool acts a global pool of WriteBuffers, that dynamically
|
||
|
// allocates and reclaims buffers in response to load.
|
||
|
type WriteBufferPool struct {
|
||
|
pool *queue.GCQueue
|
||
|
}
|
||
|
|
||
|
// NewWriteBufferPool returns a freshly instantiated WriteBufferPool, using the
|
||
|
// given gcInterval and expiryIntervals.
|
||
|
func NewWriteBufferPool(
|
||
|
gcInterval, expiryInterval time.Duration) *WriteBufferPool {
|
||
|
|
||
|
return &WriteBufferPool{
|
||
|
pool: queue.NewGCQueue(
|
||
|
newRecyclableWriteBuffer, 100,
|
||
|
gcInterval, expiryInterval,
|
||
|
),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Take returns a fresh WriteBuffer to the caller.
|
||
|
func (p *WriteBufferPool) Take() *WriteBuffer {
|
||
|
return p.pool.Take().(*WriteBuffer)
|
||
|
}
|
||
|
|
||
|
// Return returns the WriteBuffer to the pool, so that it can be recycled or
|
||
|
// released.
|
||
|
func (p *WriteBufferPool) Return(buf *WriteBuffer) {
|
||
|
p.pool.Return(buf)
|
||
|
}
|