From d18d87b37dc88b491d58ea526fd5706f94fda515 Mon Sep 17 00:00:00 2001 From: Marek Majkowski Date: Fri, 10 Jan 2014 07:46:24 -0800 Subject: [PATCH] Introduce msg.PackBuffer() - it's like msg.Pack() but can reuse a byte buffer msg.Pack() always allocates a byte slice. This is good for simplicity, but in a serious application it's preferable to reuse byte slices to reduce the GC overhead. This patch introduces a new public method: PackBuffer(). It's exaclty like Pack() but is able to reuse a given byte slice. It will still allocate a new slice if the given one is too small. --- msg.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/msg.go b/msg.go index a6ec49cb..aefc07f1 100644 --- a/msg.go +++ b/msg.go @@ -1290,6 +1290,11 @@ func (h *MsgHdr) String() string { // Pack packs a Msg: it is converted to to wire format. // If the dns.Compress is true the message will be in compressed wire format. func (dns *Msg) Pack() (msg []byte, err error) { + return dns.PackBuffer(nil) +} + +// PackWithBuffer packs a Msg, reusing a given buffer if possible to reduce memory allocations +func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) { var dh Header var compression map[string]int if dns.Compress { @@ -1335,7 +1340,11 @@ func (dns *Msg) Pack() (msg []byte, err error) { dh.Nscount = uint16(len(ns)) dh.Arcount = uint16(len(extra)) - msg = make([]byte, dns.packLen()+1) + msg = buf + if packLen := dns.packLen(); len(msg) <= packLen { + msg = make([]byte, packLen+1) + } + // Pack it in: header and then the pieces. off := 0 off, err = packStructCompress(&dh, msg, off, compression, dns.Compress)