forked from lightningnetwork/lnd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
multi: add buffer.Write and pool.WriteBuffer, make GCQueue generic
- Loading branch information
1 parent
ca4226d
commit 6f96d04
Showing
12 changed files
with
414 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package buffer_test | ||
|
||
import ( | ||
"bytes" | ||
"testing" | ||
|
||
"github.com/lightningnetwork/lnd/buffer" | ||
) | ||
|
||
// TestRecycleSlice asserts that RecycleSlice always zeros a byte slice. | ||
func TestRecycleSlice(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
slice []byte | ||
}{ | ||
{ | ||
name: "length zero", | ||
}, | ||
{ | ||
name: "length one", | ||
slice: []byte("a"), | ||
}, | ||
{ | ||
name: "length power of two length", | ||
slice: bytes.Repeat([]byte("b"), 16), | ||
}, | ||
{ | ||
name: "length non power of two", | ||
slice: bytes.Repeat([]byte("c"), 27), | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
buffer.RecycleSlice(test.slice) | ||
|
||
expSlice := make([]byte, len(test.slice)) | ||
if !bytes.Equal(expSlice, test.slice) { | ||
t.Fatalf("slice not recycled, want: %v, got: %v", | ||
expSlice, test.slice) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package buffer | ||
|
||
// RecycleSlice zeroes byte slice, 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 ~65KB buffers use for wire messages. Inspired by: | ||
// https://stackoverflow.com/questions/30614165/is-there-analog-of-memset-in-go | ||
func RecycleSlice(b []byte) { | ||
if len(b) == 0 { | ||
return | ||
} | ||
|
||
b[0] = 0 | ||
for i := 1; i < len(b); i *= 2 { | ||
copy(b[i:], b[:i]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package buffer | ||
|
||
import ( | ||
"github.com/lightningnetwork/lnd/lnwire" | ||
) | ||
|
||
// WriteSize represents the size of the maximum plaintext message than can be | ||
// sent using brontide. The buffer does not include extra space for the MAC, as | ||
// that is applied by the Noise protocol after encrypting the plaintext. | ||
const WriteSize = lnwire.MaxMessagePayload | ||
|
||
// Write is static byte array occupying to maximum-allowed plaintext-message | ||
// size. | ||
type Write [WriteSize]byte | ||
|
||
// Recycle zeroes the Write, making it fresh for another use. | ||
func (b *Write) Recycle() { | ||
RecycleSlice(b[:]) | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package pool | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/lightningnetwork/lnd/queue" | ||
) | ||
|
||
// Recycler is an interface that allows an object to be reclaimed without | ||
// needing to be returned to the runtime. | ||
type Recycler interface { | ||
// Recycle resets the object to its default state. | ||
Recycle() | ||
} | ||
|
||
// Recycle is a generic queue for recycling objects implementing the Recycler | ||
// interface. It is backed by an underlying queue.GCQueue, and invokes the | ||
// Recycle method on returned objects before returning them to the queue. | ||
type Recycle struct { | ||
queue *queue.GCQueue | ||
} | ||
|
||
// NewRecycle initializes a fresh Recycle instance. | ||
func NewRecycle(newItem func() interface{}, returnQueueSize int, | ||
gcInterval, expiryInterval time.Duration) *Recycle { | ||
|
||
return &Recycle{ | ||
queue: queue.NewGCQueue( | ||
newItem, returnQueueSize, | ||
gcInterval, expiryInterval, | ||
), | ||
} | ||
} | ||
|
||
// Take returns an element from the pool. | ||
func (r *Recycle) Take() interface{} { | ||
return r.queue.Take() | ||
} | ||
|
||
// Return returns an item implementing the Recycler interface to the pool. The | ||
// Recycle method is invoked before returning the item to improve performance | ||
// and utilization under load. | ||
func (r *Recycle) Return(item Recycler) { | ||
// Recycle the item to ensure that a dirty instance is never offered | ||
// from Take. The call is done here so that the CPU cycles spent | ||
// clearing the buffer are owned by the caller, and not by the queue | ||
// itself. This makes the queue more likely to be available to deliver | ||
// items in the free list. | ||
item.Recycle() | ||
|
||
r.queue.Return(item) | ||
} |
Oops, something went wrong.