Optimize buffer allocation logic in event encoding to reduce GC pressure and improve performance.
This commit is contained in:
@@ -112,6 +112,22 @@ func (ev *E) Marshal(dst []byte) (b []byte) {
|
|||||||
b = append(b, '"')
|
b = append(b, '"')
|
||||||
b = append(b, jId...)
|
b = append(b, jId...)
|
||||||
b = append(b, `":"`...)
|
b = append(b, `":"`...)
|
||||||
|
// it can happen the slice has insufficient capacity to hold the content AND
|
||||||
|
// the signature at this point, because the signature encoder must have
|
||||||
|
// sufficient capacity pre-allocated as it does not append to the buffer.
|
||||||
|
// unlike every other encoding function up to this point. This also ensures
|
||||||
|
// that since the bufpool defaults to 1kb, most events won't have a
|
||||||
|
// re-allocation required, but if they do, it will be this next one, and it
|
||||||
|
// integrates properly with the buffer pool, reducing GC pressure and
|
||||||
|
// avoiding new heap allocations.
|
||||||
|
if cap(b) < len(b)+len(ev.Content)+7+256+2 {
|
||||||
|
b2 := make([]byte, len(b)+len(ev.Content)*2+7+256+2)
|
||||||
|
copy(b2, b)
|
||||||
|
b2 = b2[:len(b)]
|
||||||
|
// return the old buffer to the pool for reuse.
|
||||||
|
bufpool.PutBytes(b)
|
||||||
|
b = b2
|
||||||
|
}
|
||||||
b = b[:len(b)+2*sha256.Size]
|
b = b[:len(b)+2*sha256.Size]
|
||||||
xhex.Encode(b[len(b)-2*sha256.Size:], ev.ID)
|
xhex.Encode(b[len(b)-2*sha256.Size:], ev.ID)
|
||||||
b = append(b, `","`...)
|
b = append(b, `","`...)
|
||||||
@@ -136,22 +152,6 @@ func (ev *E) Marshal(dst []byte) (b []byte) {
|
|||||||
b = append(b, `,"`...)
|
b = append(b, `,"`...)
|
||||||
b = append(b, jContent...)
|
b = append(b, jContent...)
|
||||||
b = append(b, `":"`...)
|
b = append(b, `":"`...)
|
||||||
// it can happen the slice has insufficient capacity to hold the content AND
|
|
||||||
// the signature at this point, because the signature encoder must have
|
|
||||||
// sufficient capacity pre-allocated as it does not append to the buffer.
|
|
||||||
// unlike every other encoding function up to this point. This also ensures
|
|
||||||
// that since the bufpool defaults to 1kb, most events won't have a
|
|
||||||
// re-allocation required, but if they do, it will be this next one, and it
|
|
||||||
// integrates properly with the buffer pool, reducing GC pressure and
|
|
||||||
// avoiding new heap allocations.
|
|
||||||
if cap(b) < len(b)+len(ev.Content)+7+256+2 {
|
|
||||||
b2 := make([]byte, len(b)+len(ev.Content)*2+7+256+2)
|
|
||||||
copy(b2, b)
|
|
||||||
b2 = b2[:len(b)]
|
|
||||||
// return the old buffer to the pool for reuse.
|
|
||||||
bufpool.PutBytes(b)
|
|
||||||
b = b2
|
|
||||||
}
|
|
||||||
b = text.NostrEscape(b, ev.Content)
|
b = text.NostrEscape(b, ev.Content)
|
||||||
b = append(b, `","`...)
|
b = append(b, `","`...)
|
||||||
b = append(b, jSig...)
|
b = append(b, jSig...)
|
||||||
|
|||||||
Reference in New Issue
Block a user