go-amqp/conn.go

1106 строки
28 KiB
Go
Исходник Обычный вид История

2017-04-01 23:00:36 +03:00
package amqp
import (
"bytes"
2017-04-23 04:32:50 +03:00
"crypto/tls"
"encoding/binary"
"errors"
"fmt"
"io"
2017-04-30 02:38:15 +03:00
"math"
2017-04-01 23:00:36 +03:00
"net"
"net/url"
2017-04-27 06:35:29 +03:00
"sync"
2017-04-17 06:39:31 +03:00
"time"
2021-09-16 20:32:22 +03:00
"github.com/Azure/go-amqp/internal/bitmap"
"github.com/Azure/go-amqp/internal/buffer"
"github.com/Azure/go-amqp/internal/encoding"
"github.com/Azure/go-amqp/internal/frames"
2017-04-01 23:00:36 +03:00
)
2017-05-07 04:24:06 +03:00
// Default connection options
2017-04-01 23:00:36 +03:00
const (
2017-05-07 02:57:27 +03:00
DefaultIdleTimeout = 1 * time.Minute
DefaultMaxFrameSize = 65536
DefaultMaxSessions = 65536
2017-04-30 02:38:15 +03:00
)
// ConnOption is a function for configuring an AMQP connection.
type ConnOption func(*conn) error
2017-04-01 23:00:36 +03:00
// ConnServerHostname sets the hostname sent in the AMQP
2017-04-30 02:38:15 +03:00
// Open frame and TLS ServerName (if not otherwise set).
//
// This is useful when the AMQP connection will be established
// via a pre-established TLS connection as the server may not
// know which hostname the client is attempting to connect to.
func ConnServerHostname(hostname string) ConnOption {
return func(c *conn) error {
c.hostname = hostname
return nil
}
}
2017-04-30 02:38:15 +03:00
// ConnTLS toggles TLS negotiation.
//
// Default: false.
2017-04-30 02:38:15 +03:00
func ConnTLS(enable bool) ConnOption {
return func(c *conn) error {
c.tlsNegotiation = enable
return nil
}
}
2017-04-30 02:38:15 +03:00
// ConnTLSConfig sets the tls.Config to be used during
// TLS negotiation.
//
// This option is for advanced usage, in most scenarios
// providing a URL scheme of "amqps://" or ConnTLS(true)
// is sufficient.
func ConnTLSConfig(tc *tls.Config) ConnOption {
return func(c *conn) error {
c.tlsConfig = tc
c.tlsNegotiation = true
2017-04-23 04:32:50 +03:00
return nil
}
}
2017-04-30 02:38:15 +03:00
// ConnIdleTimeout specifies the maximum period between receiving
// frames from the peer.
//
// Resolution is milliseconds. A value of zero indicates no timeout.
// This setting is in addition to TCP keepalives.
//
// Default: 1 minute.
2017-04-30 02:38:15 +03:00
func ConnIdleTimeout(d time.Duration) ConnOption {
return func(c *conn) error {
2017-04-30 02:38:15 +03:00
if d < 0 {
return errors.New("idle timeout cannot be negative")
2017-04-30 02:38:15 +03:00
}
2017-04-27 06:35:29 +03:00
c.idleTimeout = d
return nil
}
}
2017-04-30 02:38:15 +03:00
// ConnMaxFrameSize sets the maximum frame size that
// the connection will accept.
2017-04-30 02:38:15 +03:00
//
// Must be 512 or greater.
//
// Default: 512.
2017-04-30 02:38:15 +03:00
func ConnMaxFrameSize(n uint32) ConnOption {
return func(c *conn) error {
2017-04-30 02:38:15 +03:00
if n < 512 {
return errors.New("max frame size must be 512 or greater")
2017-04-30 02:38:15 +03:00
}
2017-04-27 06:35:29 +03:00
c.maxFrameSize = n
return nil
}
}
// ConnConnectTimeout configures how long to wait for the
// server during connection establishment.
//
// Once the connection has been established, ConnIdleTimeout
// applies. If duration is zero, no timeout will be applied.
//
// Default: 0.
func ConnConnectTimeout(d time.Duration) ConnOption {
return func(c *conn) error { c.connectTimeout = d; return nil }
}
2017-04-01 23:00:36 +03:00
// ConnMaxSessions sets the maximum number of channels.
//
// n must be in the range 1 to 65536.
//
// Default: 65536.
func ConnMaxSessions(n int) ConnOption {
return func(c *conn) error {
if n < 1 {
return errors.New("max sessions cannot be less than 1")
}
if n > 65536 {
return errors.New("max sessions cannot be greater than 65536")
}
c.channelMax = uint16(n - 1)
return nil
}
}
2018-02-13 21:14:36 +03:00
// ConnProperty sets an entry in the connection properties map sent to the server.
//
// This option can be used multiple times.
func ConnProperty(key, value string) ConnOption {
return func(c *conn) error {
if key == "" {
return errors.New("connection property key must not be empty")
2018-02-13 21:14:36 +03:00
}
if c.properties == nil {
c.properties = make(map[encoding.Symbol]interface{})
2018-02-13 21:14:36 +03:00
}
c.properties[encoding.Symbol(key)] = value
2018-02-13 21:14:36 +03:00
return nil
}
}
// ConnContainerID sets the container-id to use when opening the connection.
//
// A container ID will be randomly generated if this option is not used.
func ConnContainerID(id string) ConnOption {
return func(c *conn) error {
c.containerID = id
return nil
}
}
// used to abstract the underlying dialer for testing purposes
type dialer interface {
NetDialerDial(c *conn, host, port string) error
TLSDialWithDialer(c *conn, host, port string) error
}
func connDialer(d dialer) ConnOption {
return func(c *conn) error {
c.dialer = d
return nil
}
}
// conn is an AMQP connection.
// only exported fields and methods are part of public surface area,
// all others are considered to be internal implementation details.
type conn struct {
net net.Conn // underlying connection
connectTimeout time.Duration // time to wait for reads/writes during conn establishment
dialer dialer // used for testing purposes, it allows faking dialing TCP/TLS endpoints
// TLS
2017-04-30 02:38:15 +03:00
tlsNegotiation bool // negotiate TLS
tlsComplete bool // TLS negotiation complete
tlsConfig *tls.Config // TLS config, default used if nil (ServerName set to Client.hostname)
2017-04-01 23:00:36 +03:00
2017-04-30 02:38:15 +03:00
// SASL
saslHandlers map[encoding.Symbol]stateFunc // map of supported handlers keyed by SASL mechanism, SASL not negotiated if nil
saslComplete bool // SASL negotiation complete; internal *except* for SASL auth methods
2017-04-01 23:00:36 +03:00
2017-04-30 02:38:15 +03:00
// local settings
maxFrameSize uint32 // max frame size to accept
channelMax uint16 // maximum number of channels to allow
hostname string // hostname of remote server (set explicitly or parsed from URL)
idleTimeout time.Duration // maximum period between receiving frames
properties map[encoding.Symbol]interface{} // additional properties sent upon connection open
containerID string // set explicitly or randomly generated
2017-04-27 06:35:29 +03:00
2017-04-30 02:38:15 +03:00
// peer settings
peerIdleTimeout time.Duration // maximum period between sending frames
PeerMaxFrameSize uint32 // maximum frame size peer will accept
2017-04-01 23:00:36 +03:00
2017-04-30 02:38:15 +03:00
// conn state
errMu sync.Mutex // mux holds errMu from start until shutdown completes; operations are sequential before mux is started
err error // error to be returned to client; internal *except* for SASL auth methods
Done chan struct{} // indicates the connection is done
2017-04-01 23:00:36 +03:00
// mux
NewSession chan newSessionResp // new Sessions are requested from mux by reading off this channel
DelSession chan *Session // session completion is indicated to mux by sending the Session on this channel
connErr chan error // connReader/Writer notifications of an error
closeMux chan struct{} // indicates that the mux should stop
closeMuxOnce sync.Once
// connReader
rxProto chan protoHeader // protoHeaders received by connReader
rxFrame chan frames.Frame // AMQP frames received by connReader
rxDone chan struct{}
connReaderRun chan func() // functions to be run by conn reader (set deadline on conn to run)
// connWriter
txFrame chan frames.Frame // AMQP frames to be sent by connWriter
txBuf buffer.Buffer // buffer for marshaling frames before transmitting
txDone chan struct{}
}
type newSessionResp struct {
session *Session
err error
}
// implements the dialer interface
type defaultDialer struct{}
func (defaultDialer) NetDialerDial(c *conn, host, port string) (err error) {
dialer := &net.Dialer{Timeout: c.connectTimeout}
c.net, err = dialer.Dial("tcp", net.JoinHostPort(host, port))
return
}
func (defaultDialer) TLSDialWithDialer(c *conn, host, port string) (err error) {
dialer := &net.Dialer{Timeout: c.connectTimeout}
c.net, err = tls.DialWithDialer(dialer, "tcp", net.JoinHostPort(host, port), c.tlsConfig)
return
}
func dialConn(addr string, opts ...ConnOption) (*conn, error) {
u, err := url.Parse(addr)
if err != nil {
return nil, err
}
host, port := u.Hostname(), u.Port()
if port == "" {
port = "5672"
if u.Scheme == "amqps" || u.Scheme == "amqp+ssl" {
port = "5671"
}
}
// prepend SASL credentials when the user/pass segment is not empty
if u.User != nil {
pass, _ := u.User.Password()
opts = append([]ConnOption{
ConnSASLPlain(u.User.Username(), pass),
}, opts...)
}
// append default options so user specified can overwrite
opts = append([]ConnOption{
connDialer(defaultDialer{}),
ConnServerHostname(host),
}, opts...)
c, err := newConn(nil, opts...)
if err != nil {
return nil, err
}
switch u.Scheme {
case "amqp", "":
err = c.dialer.NetDialerDial(c, host, port)
case "amqps", "amqp+ssl":
c.initTLSConfig()
c.tlsNegotiation = false
err = c.dialer.TLSDialWithDialer(c, host, port)
default:
err = fmt.Errorf("unsupported scheme %q", u.Scheme)
}
if err != nil {
return nil, err
}
return c, nil
}
func newConn(netConn net.Conn, opts ...ConnOption) (*conn, error) {
c := &conn{
net: netConn,
2017-05-07 02:57:27 +03:00
maxFrameSize: DefaultMaxFrameSize,
PeerMaxFrameSize: DefaultMaxFrameSize,
channelMax: DefaultMaxSessions - 1, // -1 because channel-max starts at zero
2017-05-07 02:57:27 +03:00
idleTimeout: DefaultIdleTimeout,
containerID: randString(40),
Done: make(chan struct{}),
connErr: make(chan error, 2), // buffered to ensure connReader/Writer won't leak
closeMux: make(chan struct{}),
rxProto: make(chan protoHeader),
rxFrame: make(chan frames.Frame),
rxDone: make(chan struct{}),
connReaderRun: make(chan func(), 1), // buffered to allow queueing function before interrupt
NewSession: make(chan newSessionResp),
DelSession: make(chan *Session),
txFrame: make(chan frames.Frame),
txDone: make(chan struct{}),
}
// apply options
for _, opt := range opts {
if err := opt(c); err != nil {
return nil, err
}
}
return c, nil
}
func (c *conn) initTLSConfig() {
// create a new config if not already set
if c.tlsConfig == nil {
c.tlsConfig = new(tls.Config)
}
// TLS config must have ServerName or InsecureSkipVerify set
if c.tlsConfig.ServerName == "" && !c.tlsConfig.InsecureSkipVerify {
c.tlsConfig.ServerName = c.hostname
}
}
// Start establishes the connection and begins multiplexing network IO.
// It is an error to call Start() on a connection that's been closed.
func (c *conn) Start() error {
// start reader
go c.connReader()
// run connection establishment state machine
for state := c.negotiateProto; state != nil; {
state = state()
}
// check if err occurred
if c.err != nil {
close(c.txDone) // close here since connWriter hasn't been started yet
2018-02-17 19:24:03 +03:00
_ = c.Close()
return c.err
}
// start multiplexor and writer
go c.mux()
go c.connWriter()
return nil
2017-04-01 23:00:36 +03:00
}
// Close closes the connection.
func (c *conn) Close() error {
c.closeMuxOnce.Do(func() { close(c.closeMux) })
err := c.Err()
if err == ErrConnClosed {
return nil
}
return err
}
// close should only be called by conn.mux.
func (c *conn) close() {
close(c.Done) // notify goroutines and blocked functions to exit
// wait for writing to stop, allows it to send the final close frame
<-c.txDone
// reading from connErr in mux can race with closeMux, causing
// a pending conn read/write error to be lost. now that the
// mux has exited, drain any pending error.
select {
case err := <-c.connErr:
c.err = err
default:
// no pending read/write error
}
2017-04-24 06:24:12 +03:00
err := c.net.Close()
switch {
// conn.err already set
case c.err != nil:
// conn.err not set and c.net.Close() returned a non-nil error
case err != nil:
2017-04-24 06:24:12 +03:00
c.err = err
// no errors
default:
c.err = ErrConnClosed
2017-04-24 06:24:12 +03:00
}
// check rxDone after closing net, otherwise may block
// for up to c.idleTimeout
<-c.rxDone
2017-04-01 23:00:36 +03:00
}
// Err returns the connection's error state after it's been closed.
// Calling this on an open connection will block until the connection is closed.
func (c *conn) Err() error {
c.errMu.Lock()
defer c.errMu.Unlock()
return c.err
}
// mux is started in it's own goroutine after initial connection establishment.
// It handles muxing of sessions, keepalives, and connection errors.
func (c *conn) mux() {
var (
// allocated channels
2021-09-16 20:32:22 +03:00
channels = bitmap.New(uint32(c.channelMax))
// create the next session to allocate
// note that channel always start at 0, and 0 is special and can't be deleted
2021-09-16 20:32:22 +03:00
nextChannel, _ = channels.Next()
nextSession = newSessionResp{session: newSession(c, uint16(nextChannel))}
2017-04-01 23:00:36 +03:00
// map channels to sessions
sessionsByChannel = make(map[uint16]*Session)
sessionsByRemoteChannel = make(map[uint16]*Session)
)
2017-04-01 23:00:36 +03:00
// hold the errMu lock until error or done
2017-04-27 06:35:29 +03:00
c.errMu.Lock()
defer c.errMu.Unlock()
defer c.close() // defer order is important. c.errMu unlock indicates that connection is finally complete
2017-04-27 06:35:29 +03:00
2017-04-01 23:00:36 +03:00
for {
// check if last loop returned an error
2017-04-01 23:00:36 +03:00
if c.err != nil {
2017-04-24 06:24:12 +03:00
return
2017-04-01 23:00:36 +03:00
}
select {
// error from connReader
case c.err = <-c.connErr:
2017-04-01 23:00:36 +03:00
// new frame from connReader
case fr := <-c.rxFrame:
var (
session *Session
ok bool
)
switch body := fr.Body.(type) {
// Server initiated close.
case *frames.PerformClose:
if body.Error != nil {
c.err = body.Error
} else {
c.err = ErrConnClosed
}
return
// RemoteChannel should be used when frame is Begin
case *frames.PerformBegin:
if body.RemoteChannel == nil {
// since we only support remotely-initiated sessions, this is an error
// TODO: it would be ideal to not have this kill the connection
c.err = fmt.Errorf("%T: nil RemoteChannel", fr.Body)
break
}
session, ok = sessionsByChannel[*body.RemoteChannel]
if !ok {
c.err = fmt.Errorf("unexpected remote channel number %d, expected %d", *body.RemoteChannel, nextChannel)
break
}
session.remoteChannel = fr.Channel
sessionsByRemoteChannel[fr.Channel] = session
case *frames.PerformEnd:
session, ok = sessionsByRemoteChannel[fr.Channel]
if !ok {
c.err = fmt.Errorf("%T: didn't find channel %d in sessionsByRemoteChannel", fr.Body, fr.Channel)
break
}
// we MUST remove the remote channel from our map as soon as we receive
// the ack (i.e. before passing it on to the session mux) on the session
// ending since the numbers are recycled.
delete(sessionsByRemoteChannel, fr.Channel)
default:
// pass on performative to the correct session
session, ok = sessionsByRemoteChannel[fr.Channel]
if !ok {
c.err = fmt.Errorf("%T: didn't find channel %d in sessionsByRemoteChannel", fr.Body, fr.Channel)
}
}
if !ok {
continue
2017-04-01 23:00:36 +03:00
}
select {
case session.rx <- fr:
case <-c.closeMux:
return
}
2017-04-01 23:00:36 +03:00
// new session request
//
// Continually try to send the next session on the channel,
// then add it to the sessions map. This allows us to control ID
// allocation and prevents the need to have shared map. Since new
// sessions are far less frequent than frames being sent to sessions,
// this avoids the lock/unlock for session lookup.
case c.NewSession <- nextSession:
if nextSession.err != nil {
continue
}
// save session into map
ch := nextSession.session.channel
sessionsByChannel[ch] = nextSession.session
// get next available channel
2021-09-16 20:32:22 +03:00
next, ok := channels.Next()
if !ok {
nextSession = newSessionResp{err: fmt.Errorf("reached connection channel max (%d)", c.channelMax)}
continue
}
2017-04-01 23:00:36 +03:00
// create the next session to send
nextSession = newSessionResp{session: newSession(c, uint16(next))}
// session deletion
case s := <-c.DelSession:
delete(sessionsByChannel, s.channel)
2021-09-16 20:32:22 +03:00
channels.Remove(uint32(s.channel))
2017-04-01 23:00:36 +03:00
// connection is complete
case <-c.closeMux:
2017-04-27 06:35:29 +03:00
return
2017-04-01 23:00:36 +03:00
}
}
}
2017-04-30 02:38:15 +03:00
// connReader reads from the net.Conn, decodes frames, and passes them
// up via the conn.rxFrame and conn.rxProto channels.
func (c *conn) connReader() {
defer close(c.rxDone)
buf := &buffer.Buffer{}
2017-04-24 06:24:12 +03:00
2017-04-30 02:38:15 +03:00
var (
negotiating = true // true during conn establishment, check for protoHeaders
currentHeader frames.Header // keep track of the current header, for frames split across multiple TCP packets
frameInProgress bool // true if in the middle of receiving data for currentHeader
2017-04-30 02:38:15 +03:00
)
2017-04-27 06:35:29 +03:00
for {
switch {
// Cheaply reuse free buffer space when fully read.
case buf.Len() == 0:
buf.Reset()
// Prevent excessive/unbounded growth by shifting data to beginning of buffer.
case int64(buf.Size()) > int64(c.maxFrameSize):
buf.Reclaim()
Additional encoding/decoding optimization * Replace reader/writer interfaces with concrete `buffer` type. * Avoid intermediate buffer during map encoding. * Avoid `milliseconds` marshal allocation. * Remove `errNull`/`isNull` from marshal and avoid defer in hot path. * Cleanup of decoding code. * Minimize bounds checks by adding hints. * Check interface types last in type switches. * Add fastpath in unmarshal for `**uint32`. ``` name old time/op new time/op delta FrameMarshal/transfer-8 420ns ± 4% 197ns ± 5% -53.04% (p=0.000 n=10+10) FrameUnmarshal/transfer-8 1.84µs ± 0% 0.61µs ± 5% -66.64% (p=0.000 n=8+10) Marshal/*amqp.performOpen-8 787ns ± 3% 293ns ± 5% -62.83% (p=0.000 n=10+10) Marshal/*amqp.performBegin-8 621ns ± 1% 216ns ± 3% -65.27% (p=0.000 n=10+9) Marshal/*amqp.performAttach-8 2.45µs ± 1% 1.12µs ± 3% -54.13% (p=0.000 n=10+10) Marshal/amqp.role-8 30.5ns ± 2% 20.5ns ± 2% -32.75% (p=0.000 n=10+10) Marshal/*amqp.unsettled-8 258ns ± 8% 100ns ± 3% -61.10% (p=0.000 n=10+9) Marshal/*amqp.source-8 900ns ± 1% 401ns ± 5% -55.43% (p=0.000 n=10+10) Marshal/*amqp.target-8 516ns ± 1% 244ns ± 3% -52.79% (p=0.000 n=10+10) Marshal/*amqp.performFlow-8 576ns ± 1% 193ns ± 4% -66.42% (p=0.000 n=10+10) Marshal/*amqp.performTransfer-8 404ns ± 6% 184ns ± 2% -54.35% (p=0.000 n=10+10) Marshal/*amqp.performDisposition-8 215ns ± 5% 102ns ± 4% -52.54% (p=0.000 n=10+10) Marshal/*amqp.performDetach-8 612ns ± 2% 279ns ± 0% -54.37% (p=0.000 n=10+6) Marshal/*amqp.performDetach#01-8 1.23µs ± 8% 0.42µs ± 4% -65.71% (p=0.000 n=9+10) Marshal/amqp.ErrorCondition-8 69.9ns ± 1% 27.3ns ± 4% -60.96% (p=0.000 n=10+10) Marshal/*amqp.Error-8 493ns ± 1% 221ns ± 5% -55.12% (p=0.000 n=10+10) Marshal/*amqp.performEnd-8 595ns ± 1% 264ns ± 3% -55.69% (p=0.000 n=8+10) Marshal/*amqp.performClose-8 601ns ± 2% 263ns ± 4% -56.29% (p=0.000 n=10+10) Marshal/*amqp.Message-8 1.83µs ± 0% 0.80µs ± 4% -56.33% (p=0.000 n=8+10) Marshal/*amqp.MessageHeader-8 194ns ± 2% 82ns ± 3% -57.39% (p=0.000 n=10+10) Marshal/*amqp.MessageProperties-8 546ns ± 3% 264ns ± 5% -51.56% (p=0.000 n=8+10) Marshal/*amqp.stateReceived-8 137ns ± 3% 48ns ± 2% -65.10% (p=0.000 n=9+10) Marshal/*amqp.stateAccepted-8 30.1ns ± 2% 21.4ns ± 4% -28.80% (p=0.000 n=8+10) Marshal/*amqp.stateRejected-8 608ns ± 1% 261ns ± 3% -57.04% (p=0.000 n=10+9) Marshal/*amqp.stateReleased-8 30.6ns ± 5% 22.2ns ± 3% -27.30% (p=0.000 n=8+10) Marshal/*amqp.stateModified-8 352ns ± 4% 145ns ± 6% -58.84% (p=0.000 n=10+10) Marshal/amqp.lifetimePolicy-8 29.9ns ± 3% 19.8ns ± 3% -33.73% (p=0.000 n=10+10) Marshal/amqp.SenderSettleMode-8 35.1ns ± 3% 23.7ns ± 3% -32.44% (p=0.000 n=9+9) Marshal/amqp.ReceiverSettleMode-8 36.3ns ±13% 23.6ns ± 4% -35.07% (p=0.000 n=10+10) Marshal/*amqp.saslInit-8 160ns ± 5% 90ns ± 4% -43.69% (p=0.000 n=8+10) Marshal/*amqp.saslMechanisms-8 235ns ± 1% 74ns ± 7% -68.69% (p=0.000 n=10+10) Marshal/*amqp.saslOutcome-8 169ns ± 1% 71ns ± 9% -57.88% (p=0.000 n=10+10) Marshal/amqp.milliseconds-8 60.2ns ± 2% 19.0ns ± 5% -68.40% (p=0.000 n=10+10) Marshal/amqp.symbol-8 29.0ns ± 5% 25.1ns ± 5% -13.40% (p=0.000 n=10+10) Marshal/map[amqp.symbol]interface_{}-8 242ns ± 9% 81ns ± 2% -66.57% (p=0.000 n=10+9) Marshal/amqp.UUID-8 46.4ns ± 2% 19.2ns ± 6% -58.73% (p=0.000 n=9+10) Marshal/bool-8 16.6ns ± 5% 6.2ns ± 4% -62.82% (p=0.000 n=10+10) Marshal/int8-8 19.4ns ± 1% 8.3ns ± 5% -57.28% (p=0.000 n=9+10) Marshal/int8#01-8 19.5ns ± 2% 8.4ns ± 4% -57.10% (p=0.000 n=9+10) Marshal/int16-8 24.3ns ± 6% 6.8ns ± 5% -72.13% (p=0.000 n=10+10) Marshal/int16#01-8 24.9ns ± 2% 7.0ns ± 6% -71.90% (p=0.000 n=9+10) Marshal/int32-8 33.1ns ± 2% 6.9ns ± 3% -79.13% (p=0.000 n=9+10) Marshal/int32#01-8 32.6ns ± 5% 6.9ns ± 5% -78.94% (p=0.000 n=10+10) Marshal/int64-8 45.8ns ± 4% 7.0ns ± 4% -84.66% (p=0.000 n=10+10) Marshal/int64#01-8 45.7ns ± 3% 7.1ns ± 5% -84.54% (p=0.000 n=8+10) Marshal/uint8-8 19.0ns ± 2% 8.3ns ± 5% -56.49% (p=0.000 n=9+10) Marshal/uint16-8 24.8ns ± 4% 7.4ns ± 2% -70.23% (p=0.000 n=10+9) Marshal/uint32-8 33.4ns ± 3% 7.1ns ± 5% -78.78% (p=0.000 n=8+10) Marshal/uint64-8 46.5ns ± 3% 8.5ns ± 4% -81.78% (p=0.000 n=9+10) Marshal/float32-8 33.7ns ± 7% 7.2ns ± 6% -78.73% (p=0.000 n=10+10) Marshal/float32#01-8 33.5ns ± 3% 7.1ns ± 5% -78.89% (p=0.000 n=10+10) Marshal/float32#02-8 33.4ns ± 5% 7.0ns ± 5% -78.99% (p=0.000 n=10+10) Marshal/float32#03-8 34.1ns ± 6% 7.2ns ± 4% -78.86% (p=0.000 n=10+10) Marshal/float64-8 47.3ns ± 3% 7.4ns ± 4% -84.38% (p=0.000 n=9+10) Marshal/float64#01-8 47.3ns ± 3% 7.4ns ± 6% -84.37% (p=0.000 n=8+10) Marshal/float64#02-8 46.9ns ± 5% 7.6ns ± 1% -83.87% (p=0.000 n=10+10) Marshal/float64#03-8 47.6ns ± 4% 7.3ns ± 4% -84.57% (p=0.000 n=9+10) Marshal/amqp.describedType-8 119ns ± 5% 65ns ± 5% -45.63% (p=0.000 n=10+9) Marshal/map[interface_{}]interface_{}-8 253ns ± 9% 79ns ± 4% -68.82% (p=0.000 n=9+10) Marshal/map[string]interface_{}-8 252ns ±11% 83ns ± 3% -67.08% (p=0.000 n=10+9) Marshal/amqp.ArrayUByte-8 38.5ns ± 4% 29.6ns ± 1% -23.25% (p=0.000 n=10+9) Marshal/[]int8-8 47.2ns ± 5% 24.9ns ± 5% -47.28% (p=0.000 n=10+9) Marshal/[]uint16-8 75.1ns ± 3% 24.1ns ± 5% -67.84% (p=0.000 n=10+10) Marshal/[]uint16#01-8 75.4ns ± 4% 24.4ns ± 5% -67.60% (p=0.000 n=10+10) Marshal/[]int16-8 75.0ns ± 6% 24.6ns ± 4% -67.26% (p=0.000 n=10+10) Marshal/[]int16#01-8 73.7ns ± 4% 23.9ns ± 7% -67.64% (p=0.000 n=10+10) Marshal/[]uint32-8 106ns ± 4% 24ns ± 2% -77.50% (p=0.000 n=10+9) Marshal/[]uint32#01-8 49.6ns ± 5% 26.7ns ± 6% -46.18% (p=0.000 n=10+10) Marshal/[]int32-8 105ns ± 3% 23ns ± 4% -77.70% (p=0.000 n=10+8) Marshal/[]int32#01-8 49.0ns ± 3% 27.1ns ± 5% -44.69% (p=0.000 n=9+9) Marshal/[]uint64-8 172ns ± 4% 24ns ± 3% -85.81% (p=0.000 n=10+10) Marshal/[]uint64#01-8 49.2ns ± 3% 26.7ns ± 2% -45.72% (p=0.000 n=10+8) Marshal/[]int64-8 172ns ± 2% 25ns ± 3% -85.57% (p=0.000 n=8+9) Marshal/[]int64#01-8 49.1ns ± 4% 27.2ns ± 4% -44.62% (p=0.000 n=10+10) Marshal/[]float32-8 90.6ns ± 3% 23.0ns ± 3% -74.58% (p=0.000 n=9+9) Marshal/[]float64-8 143ns ± 6% 23ns ± 9% -83.87% (p=0.000 n=10+10) Marshal/[]bool-8 44.0ns ± 4% 21.8ns ±10% -50.45% (p=0.000 n=10+10) Marshal/[]string-8 131ns ± 6% 43ns ± 3% -67.25% (p=0.000 n=10+10) Marshal/[]amqp.symbol-8 130ns ± 3% 41ns ± 2% -68.39% (p=0.000 n=10+10) Marshal/[][]uint8-8 127ns ± 4% 37ns ± 6% -71.02% (p=0.000 n=10+8) Marshal/[]time.Time-8 58.9ns ± 4% 19.5ns ± 4% -66.87% (p=0.000 n=10+10) Marshal/[]amqp.UUID-8 55.0ns ± 2% 20.2ns ± 5% -63.20% (p=0.000 n=10+10) Marshal/[]interface_{}-8 125ns ± 3% 43ns ± 5% -65.89% (p=0.000 n=8+10) Unmarshal/*amqp.performOpen-8 1.65µs ± 3% 0.91µs ±15% -44.61% (p=0.000 n=10+10) Unmarshal/*amqp.performBegin-8 1.33µs ± 4% 0.78µs ±14% -41.35% (p=0.000 n=10+10) Unmarshal/*amqp.performAttach-8 6.09µs ± 6% 3.80µs ±17% -37.52% (p=0.000 n=10+10) Unmarshal/amqp.role-8 215ns ±14% 58ns ± 8% -73.18% (p=0.000 n=10+10) Unmarshal/*amqp.unsettled-8 938ns ±20% 629ns ± 9% -33.01% (p=0.000 n=10+9) Unmarshal/*amqp.source-8 2.19µs ±11% 1.43µs ±25% -34.87% (p=0.000 n=10+10) Unmarshal/*amqp.target-8 1.29µs ± 5% 0.78µs ± 9% -39.50% (p=0.000 n=10+10) Unmarshal/*amqp.performFlow-8 1.82µs ± 1% 0.77µs ±15% -57.89% (p=0.000 n=10+10) Unmarshal/*amqp.performTransfer-8 1.71µs ± 2% 0.47µs ± 1% -72.26% (p=0.000 n=10+10) Unmarshal/*amqp.performDisposition-8 910ns ± 1% 242ns ± 1% -73.37% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach-8 1.49µs ± 3% 0.85µs ± 9% -42.86% (p=0.000 n=10+9) Unmarshal/*amqp.performDetach#01-8 1.93µs ± 7% 1.22µs ±13% -36.82% (p=0.000 n=10+10) Unmarshal/amqp.ErrorCondition-8 271ns ±15% 92ns ±14% -65.93% (p=0.000 n=10+10) Unmarshal/*amqp.Error-8 1.19µs ± 9% 0.76µs ±17% -36.36% (p=0.000 n=10+10) Unmarshal/*amqp.performEnd-8 1.38µs ± 4% 0.86µs ±23% -37.86% (p=0.000 n=10+10) Unmarshal/*amqp.performClose-8 1.32µs ± 2% 0.82µs ± 8% -38.12% (p=0.000 n=8+10) Unmarshal/*amqp.Message-8 4.66µs ± 4% 2.94µs ±16% -36.87% (p=0.000 n=10+10) Unmarshal/*amqp.MessageHeader-8 647ns ± 0% 206ns ± 1% -68.18% (p=0.000 n=8+9) Unmarshal/*amqp.MessageProperties-8 1.47µs ± 1% 0.53µs ± 1% -63.75% (p=0.000 n=10+10) Unmarshal/*amqp.stateReceived-8 385ns ± 2% 126ns ± 1% -67.23% (p=0.000 n=9+10) Unmarshal/*amqp.stateAccepted-8 255ns ±17% 94ns ± 3% -63.08% (p=0.000 n=10+10) Unmarshal/*amqp.stateRejected-8 1.40µs ± 4% 0.87µs ±11% -38.12% (p=0.000 n=9+10) Unmarshal/*amqp.stateReleased-8 251ns ± 9% 94ns ± 4% -62.81% (p=0.000 n=10+10) Unmarshal/*amqp.stateModified-8 1.01µs ± 8% 0.68µs ±21% -33.07% (p=0.000 n=9+10) Unmarshal/amqp.lifetimePolicy-8 203ns ± 7% 63ns ± 7% -68.74% (p=0.000 n=10+9) Unmarshal/amqp.SenderSettleMode-8 218ns ± 9% 57ns ±21% -73.84% (p=0.000 n=9+10) Unmarshal/amqp.ReceiverSettleMode-8 221ns ±11% 57ns ± 7% -74.38% (p=0.000 n=10+9) Unmarshal/*amqp.saslInit-8 551ns ± 1% 220ns ± 1% -60.10% (p=0.000 n=10+10) Unmarshal/*amqp.saslMechanisms-8 420ns ± 2% 187ns ± 1% -55.35% (p=0.000 n=10+9) Unmarshal/*amqp.saslOutcome-8 511ns ± 2% 187ns ± 2% -63.46% (p=0.000 n=10+9) Unmarshal/amqp.milliseconds-8 189ns ±22% 60ns ±17% -68.31% (p=0.000 n=10+10) Unmarshal/amqp.symbol-8 201ns ±12% 74ns ±21% -63.44% (p=0.000 n=10+10) Unmarshal/map[amqp.symbol]interface_{}-8 897ns ±31% 614ns ±16% -31.57% (p=0.000 n=10+10) Unmarshal/amqp.UUID-8 215ns ±16% 66ns ±12% -69.16% (p=0.000 n=10+10) Unmarshal/bool-8 174ns ±34% 56ns ±10% -67.75% (p=0.000 n=10+10) Unmarshal/int8-8 201ns ±26% 54ns ±17% -72.95% (p=0.000 n=10+10) Unmarshal/int8#01-8 175ns ±23% 57ns ±21% -67.47% (p=0.000 n=10+10) Unmarshal/int16-8 189ns ±15% 56ns ±16% -70.29% (p=0.000 n=10+10) Unmarshal/int16#01-8 185ns ±22% 55ns ±17% -70.31% (p=0.000 n=10+10) Unmarshal/int32-8 198ns ±13% 53ns ±11% -73.27% (p=0.000 n=10+9) Unmarshal/int32#01-8 200ns ±14% 55ns ±13% -72.32% (p=0.000 n=10+10) Unmarshal/int64-8 206ns ±16% 56ns ±19% -72.93% (p=0.000 n=10+10) Unmarshal/int64#01-8 190ns ±14% 52ns ±12% -72.48% (p=0.000 n=10+9) Unmarshal/uint8-8 188ns ±11% 55ns ±13% -70.70% (p=0.000 n=10+10) Unmarshal/uint16-8 197ns ±12% 55ns ±11% -72.16% (p=0.000 n=10+10) Unmarshal/uint32-8 187ns ±14% 57ns ±10% -69.62% (p=0.000 n=8+9) Unmarshal/uint64-8 174ns ±23% 54ns ±27% -68.90% (p=0.000 n=10+10) Unmarshal/float32-8 198ns ±24% 55ns ±20% -72.17% (p=0.000 n=10+10) Unmarshal/float32#01-8 187ns ±15% 55ns ±12% -70.82% (p=0.000 n=10+10) Unmarshal/float32#02-8 186ns ±19% 56ns ±13% -69.76% (p=0.000 n=10+10) Unmarshal/float32#03-8 184ns ±12% 52ns ±13% -71.93% (p=0.000 n=10+10) Unmarshal/float64-8 179ns ± 7% 54ns ± 7% -69.55% (p=0.000 n=9+10) Unmarshal/float64#01-8 188ns ±17% 54ns ±16% -71.39% (p=0.000 n=10+10) Unmarshal/float64#02-8 186ns ±15% 55ns ±19% -70.35% (p=0.000 n=10+10) Unmarshal/float64#03-8 185ns ±13% 56ns ±21% -69.69% (p=0.000 n=10+10) Unmarshal/amqp.describedType-8 413ns ±12% 203ns ±11% -50.91% (p=0.000 n=10+10) Unmarshal/map[interface_{}]interface_{}-8 774ns ±22% 618ns ±17% -20.15% (p=0.000 n=10+10) Unmarshal/map[string]interface_{}-8 769ns ±35% 591ns ±17% -23.16% (p=0.015 n=10+10) Unmarshal/amqp.ArrayUByte-8 203ns ±16% 88ns ±10% -56.70% (p=0.000 n=10+10) Unmarshal/[]int8-8 205ns ±12% 58ns ±10% -71.96% (p=0.000 n=9+9) Unmarshal/[]uint16-8 194ns ±14% 63ns ±18% -67.66% (p=0.000 n=10+10) Unmarshal/[]uint16#01-8 194ns ±20% 62ns ±12% -68.16% (p=0.000 n=10+10) Unmarshal/[]int16-8 200ns ±12% 61ns ± 6% -69.48% (p=0.000 n=10+9) Unmarshal/[]int16#01-8 200ns ± 7% 64ns ±14% -68.04% (p=0.000 n=10+10) Unmarshal/[]uint32-8 193ns ±16% 61ns ±10% -68.53% (p=0.000 n=10+10) Unmarshal/[]uint32#01-8 200ns ±20% 58ns ±11% -70.86% (p=0.000 n=10+10) Unmarshal/[]int32-8 201ns ±20% 64ns ±15% -68.14% (p=0.000 n=10+10) Unmarshal/[]int32#01-8 187ns ±14% 60ns ±17% -67.67% (p=0.000 n=9+10) Unmarshal/[]uint64-8 182ns ±12% 63ns ±12% -65.47% (p=0.000 n=10+10) Unmarshal/[]uint64#01-8 207ns ± 8% 60ns ±16% -70.82% (p=0.000 n=9+10) Unmarshal/[]int64-8 202ns ±20% 64ns ±10% -68.57% (p=0.000 n=10+10) Unmarshal/[]int64#01-8 197ns ±19% 56ns ± 9% -71.50% (p=0.000 n=10+9) Unmarshal/[]float32-8 197ns ±14% 61ns ±16% -68.78% (p=0.000 n=10+9) Unmarshal/[]float64-8 202ns ±16% 64ns ± 7% -68.32% (p=0.000 n=10+9) Unmarshal/[]bool-8 195ns ±15% 61ns ± 6% -68.76% (p=0.000 n=10+9) Unmarshal/[]string-8 249ns ±10% 109ns ± 5% -56.19% (p=0.000 n=10+10) Unmarshal/[]amqp.symbol-8 253ns ± 9% 110ns ± 5% -56.60% (p=0.000 n=10+10) Unmarshal/[][]uint8-8 285ns ± 3% 139ns ± 6% -51.29% (p=0.000 n=8+10) Unmarshal/[]time.Time-8 192ns ±15% 61ns ± 6% -68.44% (p=0.000 n=10+10) Unmarshal/[]amqp.UUID-8 192ns ±12% 61ns ±12% -67.98% (p=0.000 n=10+10) Unmarshal/[]interface_{}-8 296ns ± 8% 142ns ± 4% -51.92% (p=0.000 n=9+10) name old alloc/op new alloc/op delta FrameMarshal/transfer-8 0.00B 0.00B ~ (all equal) FrameUnmarshal/transfer-8 312B ± 0% 232B ± 0% -25.64% (p=0.000 n=10+10) Marshal/*amqp.performOpen-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performBegin-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performAttach-8 576B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.role-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.unsettled-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.source-8 230B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.target-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performFlow-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performTransfer-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.performDisposition-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.performDetach-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performDetach#01-8 617B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.ErrorCondition-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.Error-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performEnd-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performClose-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.Message-8 464B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageHeader-8 4.00B ± 0% 0.00B -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageProperties-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateReceived-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateAccepted-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateRejected-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.stateReleased-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateModified-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.lifetimePolicy-8 0.00B 0.00B ~ (all equal) Marshal/amqp.SenderSettleMode-8 0.00B 0.00B ~ (all equal) Marshal/amqp.ReceiverSettleMode-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.saslInit-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.saslMechanisms-8 32.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.saslOutcome-8 32.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/amqp.milliseconds-8 4.00B ± 0% 0.00B -100.00% (p=0.000 n=10+10) Marshal/amqp.symbol-8 0.00B 0.00B ~ (all equal) Marshal/map[amqp.symbol]interface_{}-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.UUID-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/bool-8 0.00B 0.00B ~ (all equal) Marshal/int8-8 0.00B 0.00B ~ (all equal) Marshal/int8#01-8 0.00B 0.00B ~ (all equal) Marshal/int16-8 0.00B 0.00B ~ (all equal) Marshal/int16#01-8 0.00B 0.00B ~ (all equal) Marshal/int32-8 0.00B 0.00B ~ (all equal) Marshal/int32#01-8 0.00B 0.00B ~ (all equal) Marshal/int64-8 0.00B 0.00B ~ (all equal) Marshal/int64#01-8 0.00B 0.00B ~ (all equal) Marshal/uint8-8 0.00B 0.00B ~ (all equal) Marshal/uint16-8 0.00B 0.00B ~ (all equal) Marshal/uint32-8 0.00B 0.00B ~ (all equal) Marshal/uint64-8 0.00B 0.00B ~ (all equal) Marshal/float32-8 0.00B 0.00B ~ (all equal) Marshal/float32#01-8 0.00B 0.00B ~ (all equal) Marshal/float32#02-8 0.00B 0.00B ~ (all equal) Marshal/float32#03-8 0.00B 0.00B ~ (all equal) Marshal/float64-8 0.00B 0.00B ~ (all equal) Marshal/float64#01-8 0.00B 0.00B ~ (all equal) Marshal/float64#02-8 0.00B 0.00B ~ (all equal) Marshal/float64#03-8 0.00B 0.00B ~ (all equal) Marshal/amqp.describedType-8 0.00B 0.00B ~ (all equal) Marshal/map[interface_{}]interface_{}-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/map[string]interface_{}-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.ArrayUByte-8 0.00B 0.00B ~ (all equal) Marshal/[]int8-8 0.00B 0.00B ~ (all equal) Marshal/[]uint16-8 0.00B 0.00B ~ (all equal) Marshal/[]uint16#01-8 0.00B 0.00B ~ (all equal) Marshal/[]int16-8 0.00B 0.00B ~ (all equal) Marshal/[]int16#01-8 0.00B 0.00B ~ (all equal) Marshal/[]uint32-8 0.00B 0.00B ~ (all equal) Marshal/[]uint32#01-8 0.00B 0.00B ~ (all equal) Marshal/[]int32-8 0.00B 0.00B ~ (all equal) Marshal/[]int32#01-8 0.00B 0.00B ~ (all equal) Marshal/[]uint64-8 0.00B 0.00B ~ (all equal) Marshal/[]uint64#01-8 0.00B 0.00B ~ (all equal) Marshal/[]int64-8 0.00B 0.00B ~ (all equal) Marshal/[]int64#01-8 0.00B 0.00B ~ (all equal) Marshal/[]float32-8 0.00B 0.00B ~ (all equal) Marshal/[]float64-8 0.00B 0.00B ~ (all equal) Marshal/[]bool-8 0.00B 0.00B ~ (all equal) Marshal/[]string-8 0.00B 0.00B ~ (all equal) Marshal/[]amqp.symbol-8 0.00B 0.00B ~ (all equal) Marshal/[][]uint8-8 0.00B 0.00B ~ (all equal) Marshal/[]time.Time-8 0.00B 0.00B ~ (all equal) Marshal/[]amqp.UUID-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/[]interface_{}-8 0.00B 0.00B ~ (all equal) Unmarshal/*amqp.performOpen-8 544B ± 0% 464B ± 0% -14.71% (p=0.000 n=10+10) Unmarshal/*amqp.performBegin-8 496B ± 0% 416B ± 0% -16.13% (p=0.000 n=10+10) Unmarshal/*amqp.performAttach-8 2.08kB ± 0% 2.00kB ± 0% -3.85% (p=0.000 n=10+10) Unmarshal/amqp.role-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.unsettled-8 480B ± 0% 400B ± 0% -16.67% (p=0.000 n=10+10) Unmarshal/*amqp.source-8 928B ± 0% 848B ± 0% -8.62% (p=0.000 n=10+10) Unmarshal/*amqp.target-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performFlow-8 464B ± 0% 400B ± 0% -13.79% (p=0.000 n=10+10) Unmarshal/*amqp.performTransfer-8 168B ± 0% 96B ± 0% -42.86% (p=0.000 n=10+10) Unmarshal/*amqp.performDisposition-8 112B ± 0% 36B ± 0% -67.86% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach#01-8 728B ± 0% 648B ± 0% -10.99% (p=0.000 n=10+10) Unmarshal/amqp.ErrorCondition-8 128B ± 0% 48B ± 0% -62.50% (p=0.000 n=10+10) Unmarshal/*amqp.Error-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performEnd-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performClose-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.Message-8 1.73kB ± 0% 1.65kB ± 0% -4.63% (p=0.000 n=10+10) Unmarshal/*amqp.MessageHeader-8 128B ± 0% 48B ± 0% -62.50% (p=0.000 n=10+10) Unmarshal/*amqp.MessageProperties-8 208B ± 0% 128B ± 0% -38.46% (p=0.000 n=10+10) Unmarshal/*amqp.stateReceived-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.stateAccepted-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.stateRejected-8 517B ± 0% 437B ± 0% -15.47% (p=0.000 n=10+10) Unmarshal/*amqp.stateReleased-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.stateModified-8 480B ± 0% 400B ± 0% -16.67% (p=0.000 n=10+10) Unmarshal/amqp.lifetimePolicy-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.SenderSettleMode-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.ReceiverSettleMode-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.saslInit-8 134B ± 0% 54B ± 0% -59.70% (p=0.000 n=10+10) Unmarshal/*amqp.saslMechanisms-8 121B ± 0% 41B ± 0% -66.12% (p=0.000 n=10+10) Unmarshal/*amqp.saslOutcome-8 144B ± 0% 64B ± 0% -55.56% (p=0.000 n=10+10) Unmarshal/amqp.milliseconds-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.symbol-8 120B ± 0% 40B ± 0% -66.67% (p=0.000 n=10+10) Unmarshal/map[amqp.symbol]interface_{}-8 500B ± 0% 420B ± 0% -16.00% (p=0.000 n=10+10) Unmarshal/amqp.UUID-8 128B ± 0% 32B ± 0% -75.00% (p=0.000 n=10+10) Unmarshal/bool-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int8-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int8#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int16#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint8-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32#02-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32#03-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64#02-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64#03-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.describedType-8 184B ± 0% 104B ± 0% -43.48% (p=0.000 n=10+10) Unmarshal/map[interface_{}]interface_{}-8 500B ± 0% 420B ± 0% -16.00% (p=0.000 n=10+10) Unmarshal/map[string]interface_{}-8 500B ± 0% 420B ± 0% -16.00% (p=0.000 n=10+10) Unmarshal/amqp.ArrayUByte-8 112B ± 0% 40B ± 0% -64.29% (p=0.000 n=10+10) Unmarshal/[]int8-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint16#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int16#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]float32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]float64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]bool-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]string-8 121B ± 0% 41B ± 0% -66.12% (p=0.000 n=10+10) Unmarshal/[]amqp.symbol-8 121B ± 0% 41B ± 0% -66.12% (p=0.000 n=10+10) Unmarshal/[][]uint8-8 136B ± 0% 56B ± 0% -58.82% (p=0.000 n=10+10) Unmarshal/[]time.Time-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]amqp.UUID-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]interface_{}-8 136B ± 0% 56B ± 0% -58.82% (p=0.000 n=10+10) name old allocs/op new allocs/op delta FrameMarshal/transfer-8 0.00 0.00 ~ (all equal) FrameUnmarshal/transfer-8 8.00 ± 0% 8.00 ± 0% ~ (all equal) Marshal/*amqp.performOpen-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performBegin-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performAttach-8 10.0 ± 0% 0.0 -100.00% (p=0.000 n=10+10) Marshal/amqp.role-8 0.00 0.00 ~ (all equal) Marshal/*amqp.unsettled-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.source-8 4.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.target-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performFlow-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performTransfer-8 0.00 0.00 ~ (all equal) Marshal/*amqp.performDisposition-8 0.00 0.00 ~ (all equal) Marshal/*amqp.performDetach-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performDetach#01-8 4.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.ErrorCondition-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.Error-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performEnd-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performClose-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.Message-8 9.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageHeader-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageProperties-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateReceived-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateAccepted-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateRejected-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.stateReleased-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateModified-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.lifetimePolicy-8 0.00 0.00 ~ (all equal) Marshal/amqp.SenderSettleMode-8 0.00 0.00 ~ (all equal) Marshal/amqp.ReceiverSettleMode-8 0.00 0.00 ~ (all equal) Marshal/*amqp.saslInit-8 0.00 0.00 ~ (all equal) Marshal/*amqp.saslMechanisms-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.saslOutcome-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.milliseconds-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.symbol-8 0.00 0.00 ~ (all equal) Marshal/map[amqp.symbol]interface_{}-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.UUID-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/bool-8 0.00 0.00 ~ (all equal) Marshal/int8-8 0.00 0.00 ~ (all equal) Marshal/int8#01-8 0.00 0.00 ~ (all equal) Marshal/int16-8 0.00 0.00 ~ (all equal) Marshal/int16#01-8 0.00 0.00 ~ (all equal) Marshal/int32-8 0.00 0.00 ~ (all equal) Marshal/int32#01-8 0.00 0.00 ~ (all equal) Marshal/int64-8 0.00 0.00 ~ (all equal) Marshal/int64#01-8 0.00 0.00 ~ (all equal) Marshal/uint8-8 0.00 0.00 ~ (all equal) Marshal/uint16-8 0.00 0.00 ~ (all equal) Marshal/uint32-8 0.00 0.00 ~ (all equal) Marshal/uint64-8 0.00 0.00 ~ (all equal) Marshal/float32-8 0.00 0.00 ~ (all equal) Marshal/float32#01-8 0.00 0.00 ~ (all equal) Marshal/float32#02-8 0.00 0.00 ~ (all equal) Marshal/float32#03-8 0.00 0.00 ~ (all equal) Marshal/float64-8 0.00 0.00 ~ (all equal) Marshal/float64#01-8 0.00 0.00 ~ (all equal) Marshal/float64#02-8 0.00 0.00 ~ (all equal) Marshal/float64#03-8 0.00 0.00 ~ (all equal) Marshal/amqp.describedType-8 0.00 0.00 ~ (all equal) Marshal/map[interface_{}]interface_{}-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/map[string]interface_{}-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.ArrayUByte-8 0.00 0.00 ~ (all equal) Marshal/[]int8-8 0.00 0.00 ~ (all equal) Marshal/[]uint16-8 0.00 0.00 ~ (all equal) Marshal/[]uint16#01-8 0.00 0.00 ~ (all equal) Marshal/[]int16-8 0.00 0.00 ~ (all equal) Marshal/[]int16#01-8 0.00 0.00 ~ (all equal) Marshal/[]uint32-8 0.00 0.00 ~ (all equal) Marshal/[]uint32#01-8 0.00 0.00 ~ (all equal) Marshal/[]int32-8 0.00 0.00 ~ (all equal) Marshal/[]int32#01-8 0.00 0.00 ~ (all equal) Marshal/[]uint64-8 0.00 0.00 ~ (all equal) Marshal/[]uint64#01-8 0.00 0.00 ~ (all equal) Marshal/[]int64-8 0.00 0.00 ~ (all equal) Marshal/[]int64#01-8 0.00 0.00 ~ (all equal) Marshal/[]float32-8 0.00 0.00 ~ (all equal) Marshal/[]float64-8 0.00 0.00 ~ (all equal) Marshal/[]bool-8 0.00 0.00 ~ (all equal) Marshal/[]string-8 0.00 0.00 ~ (all equal) Marshal/[]amqp.symbol-8 0.00 0.00 ~ (all equal) Marshal/[][]uint8-8 0.00 0.00 ~ (all equal) Marshal/[]time.Time-8 0.00 0.00 ~ (all equal) Marshal/[]amqp.UUID-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/[]interface_{}-8 0.00 0.00 ~ (all equal) Unmarshal/*amqp.performOpen-8 13.0 ± 0% 13.0 ± 0% ~ (all equal) Unmarshal/*amqp.performBegin-8 8.00 ± 0% 8.00 ± 0% ~ (all equal) Unmarshal/*amqp.performAttach-8 33.0 ± 0% 33.0 ± 0% ~ (all equal) Unmarshal/amqp.role-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.unsettled-8 5.00 ± 0% 5.00 ± 0% ~ (all equal) Unmarshal/*amqp.source-8 15.0 ± 0% 15.0 ± 0% ~ (all equal) Unmarshal/*amqp.target-8 8.00 ± 0% 8.00 ± 0% ~ (all equal) Unmarshal/*amqp.performFlow-8 5.00 ± 0% 10.00 ± 0% +100.00% (p=0.000 n=10+10) Unmarshal/*amqp.performTransfer-8 4.00 ± 0% 6.00 ± 0% +50.00% (p=0.000 n=10+10) Unmarshal/*amqp.performDisposition-8 1.00 ± 0% 2.00 ± 0% +100.00% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.performDetach#01-8 15.0 ± 0% 15.0 ± 0% ~ (all equal) Unmarshal/amqp.ErrorCondition-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/*amqp.Error-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.performEnd-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.performClose-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.Message-8 33.0 ± 0% 33.0 ± 0% ~ (all equal) Unmarshal/*amqp.MessageHeader-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/*amqp.MessageProperties-8 12.0 ± 0% 12.0 ± 0% ~ (all equal) Unmarshal/*amqp.stateReceived-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.stateAccepted-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.stateRejected-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.stateReleased-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.stateModified-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/amqp.lifetimePolicy-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.SenderSettleMode-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.ReceiverSettleMode-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.saslInit-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/*amqp.saslMechanisms-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/*amqp.saslOutcome-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/amqp.milliseconds-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.symbol-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/map[amqp.symbol]interface_{}-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/amqp.UUID-8 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) Unmarshal/bool-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int8-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int8#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int16#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint8-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32#02-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32#03-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64#02-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64#03-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.describedType-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/map[interface_{}]interface_{}-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/map[string]interface_{}-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/amqp.ArrayUByte-8 1.00 ± 0% 2.00 ± 0% +100.00% (p=0.000 n=10+10) Unmarshal/[]int8-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint16#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int16#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]float32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]float64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]bool-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]string-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/[]amqp.symbol-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/[][]uint8-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/[]time.Time-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]amqp.UUID-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]interface_{}-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) ```
2018-02-03 22:54:49 +03:00
}
// need to read more if buf doesn't contain the complete frame
// or there's not enough in buf to parse the header
if frameInProgress || buf.Len() < frames.HeaderSize {
2018-06-01 06:34:23 +03:00
if c.idleTimeout > 0 {
_ = c.net.SetReadDeadline(time.Now().Add(c.idleTimeout))
}
err := buf.ReadFromOnce(c.net)
2017-04-27 06:35:29 +03:00
if err != nil {
debug(1, "connReader error: %v", err)
select {
// check if error was due to close in progress
case <-c.Done:
return
// if there is a pending connReaderRun function, execute it
case f := <-c.connReaderRun:
f()
continue
// send error to mux and return
default:
c.connErr <- err
return
}
2017-04-24 06:24:12 +03:00
}
2017-04-27 06:35:29 +03:00
}
// read more if buf doesn't contain enough to parse the header
if buf.Len() < frames.HeaderSize {
2017-04-27 06:35:29 +03:00
continue
}
// during negotiation, check for proto frames
if negotiating && bytes.Equal(buf.Bytes()[:4], []byte{'A', 'M', 'Q', 'P'}) {
2017-04-30 02:38:15 +03:00
p, err := parseProtoHeader(buf)
if err != nil {
c.connErr <- err
2017-04-24 06:24:12 +03:00
return
}
// negotiation is complete once an AMQP proto frame is received
2017-04-27 06:35:29 +03:00
if p.ProtoID == protoAMQP {
negotiating = false
2017-04-24 06:24:12 +03:00
}
// send proto header
2017-04-24 06:24:12 +03:00
select {
case <-c.Done:
2017-04-24 06:24:12 +03:00
return
2017-04-27 06:35:29 +03:00
case c.rxProto <- p:
}
2017-04-30 02:38:15 +03:00
2017-04-27 06:35:29 +03:00
continue
}
// parse the header if a frame isn't in progress
2017-04-27 06:35:29 +03:00
if !frameInProgress {
var err error
currentHeader, err = frames.ParseHeader(buf)
2017-04-27 06:35:29 +03:00
if err != nil {
c.connErr <- err
2017-04-27 06:35:29 +03:00
return
}
frameInProgress = true
}
// check size is reasonable
2017-04-30 02:38:15 +03:00
if currentHeader.Size > math.MaxInt32 { // make max size configurable
c.connErr <- errors.New("payload too large")
2017-04-30 02:38:15 +03:00
return
}
bodySize := int64(currentHeader.Size - frames.HeaderSize)
2017-04-30 02:38:15 +03:00
// the full frame has been received
if int64(buf.Len()) < bodySize {
2017-04-27 06:35:29 +03:00
continue
}
frameInProgress = false
// check if body is empty (keepalive)
2017-04-30 02:38:15 +03:00
if bodySize == 0 {
continue
2017-04-30 02:38:15 +03:00
}
// parse the frame
b, ok := buf.Next(bodySize)
Additional encoding/decoding optimization * Replace reader/writer interfaces with concrete `buffer` type. * Avoid intermediate buffer during map encoding. * Avoid `milliseconds` marshal allocation. * Remove `errNull`/`isNull` from marshal and avoid defer in hot path. * Cleanup of decoding code. * Minimize bounds checks by adding hints. * Check interface types last in type switches. * Add fastpath in unmarshal for `**uint32`. ``` name old time/op new time/op delta FrameMarshal/transfer-8 420ns ± 4% 197ns ± 5% -53.04% (p=0.000 n=10+10) FrameUnmarshal/transfer-8 1.84µs ± 0% 0.61µs ± 5% -66.64% (p=0.000 n=8+10) Marshal/*amqp.performOpen-8 787ns ± 3% 293ns ± 5% -62.83% (p=0.000 n=10+10) Marshal/*amqp.performBegin-8 621ns ± 1% 216ns ± 3% -65.27% (p=0.000 n=10+9) Marshal/*amqp.performAttach-8 2.45µs ± 1% 1.12µs ± 3% -54.13% (p=0.000 n=10+10) Marshal/amqp.role-8 30.5ns ± 2% 20.5ns ± 2% -32.75% (p=0.000 n=10+10) Marshal/*amqp.unsettled-8 258ns ± 8% 100ns ± 3% -61.10% (p=0.000 n=10+9) Marshal/*amqp.source-8 900ns ± 1% 401ns ± 5% -55.43% (p=0.000 n=10+10) Marshal/*amqp.target-8 516ns ± 1% 244ns ± 3% -52.79% (p=0.000 n=10+10) Marshal/*amqp.performFlow-8 576ns ± 1% 193ns ± 4% -66.42% (p=0.000 n=10+10) Marshal/*amqp.performTransfer-8 404ns ± 6% 184ns ± 2% -54.35% (p=0.000 n=10+10) Marshal/*amqp.performDisposition-8 215ns ± 5% 102ns ± 4% -52.54% (p=0.000 n=10+10) Marshal/*amqp.performDetach-8 612ns ± 2% 279ns ± 0% -54.37% (p=0.000 n=10+6) Marshal/*amqp.performDetach#01-8 1.23µs ± 8% 0.42µs ± 4% -65.71% (p=0.000 n=9+10) Marshal/amqp.ErrorCondition-8 69.9ns ± 1% 27.3ns ± 4% -60.96% (p=0.000 n=10+10) Marshal/*amqp.Error-8 493ns ± 1% 221ns ± 5% -55.12% (p=0.000 n=10+10) Marshal/*amqp.performEnd-8 595ns ± 1% 264ns ± 3% -55.69% (p=0.000 n=8+10) Marshal/*amqp.performClose-8 601ns ± 2% 263ns ± 4% -56.29% (p=0.000 n=10+10) Marshal/*amqp.Message-8 1.83µs ± 0% 0.80µs ± 4% -56.33% (p=0.000 n=8+10) Marshal/*amqp.MessageHeader-8 194ns ± 2% 82ns ± 3% -57.39% (p=0.000 n=10+10) Marshal/*amqp.MessageProperties-8 546ns ± 3% 264ns ± 5% -51.56% (p=0.000 n=8+10) Marshal/*amqp.stateReceived-8 137ns ± 3% 48ns ± 2% -65.10% (p=0.000 n=9+10) Marshal/*amqp.stateAccepted-8 30.1ns ± 2% 21.4ns ± 4% -28.80% (p=0.000 n=8+10) Marshal/*amqp.stateRejected-8 608ns ± 1% 261ns ± 3% -57.04% (p=0.000 n=10+9) Marshal/*amqp.stateReleased-8 30.6ns ± 5% 22.2ns ± 3% -27.30% (p=0.000 n=8+10) Marshal/*amqp.stateModified-8 352ns ± 4% 145ns ± 6% -58.84% (p=0.000 n=10+10) Marshal/amqp.lifetimePolicy-8 29.9ns ± 3% 19.8ns ± 3% -33.73% (p=0.000 n=10+10) Marshal/amqp.SenderSettleMode-8 35.1ns ± 3% 23.7ns ± 3% -32.44% (p=0.000 n=9+9) Marshal/amqp.ReceiverSettleMode-8 36.3ns ±13% 23.6ns ± 4% -35.07% (p=0.000 n=10+10) Marshal/*amqp.saslInit-8 160ns ± 5% 90ns ± 4% -43.69% (p=0.000 n=8+10) Marshal/*amqp.saslMechanisms-8 235ns ± 1% 74ns ± 7% -68.69% (p=0.000 n=10+10) Marshal/*amqp.saslOutcome-8 169ns ± 1% 71ns ± 9% -57.88% (p=0.000 n=10+10) Marshal/amqp.milliseconds-8 60.2ns ± 2% 19.0ns ± 5% -68.40% (p=0.000 n=10+10) Marshal/amqp.symbol-8 29.0ns ± 5% 25.1ns ± 5% -13.40% (p=0.000 n=10+10) Marshal/map[amqp.symbol]interface_{}-8 242ns ± 9% 81ns ± 2% -66.57% (p=0.000 n=10+9) Marshal/amqp.UUID-8 46.4ns ± 2% 19.2ns ± 6% -58.73% (p=0.000 n=9+10) Marshal/bool-8 16.6ns ± 5% 6.2ns ± 4% -62.82% (p=0.000 n=10+10) Marshal/int8-8 19.4ns ± 1% 8.3ns ± 5% -57.28% (p=0.000 n=9+10) Marshal/int8#01-8 19.5ns ± 2% 8.4ns ± 4% -57.10% (p=0.000 n=9+10) Marshal/int16-8 24.3ns ± 6% 6.8ns ± 5% -72.13% (p=0.000 n=10+10) Marshal/int16#01-8 24.9ns ± 2% 7.0ns ± 6% -71.90% (p=0.000 n=9+10) Marshal/int32-8 33.1ns ± 2% 6.9ns ± 3% -79.13% (p=0.000 n=9+10) Marshal/int32#01-8 32.6ns ± 5% 6.9ns ± 5% -78.94% (p=0.000 n=10+10) Marshal/int64-8 45.8ns ± 4% 7.0ns ± 4% -84.66% (p=0.000 n=10+10) Marshal/int64#01-8 45.7ns ± 3% 7.1ns ± 5% -84.54% (p=0.000 n=8+10) Marshal/uint8-8 19.0ns ± 2% 8.3ns ± 5% -56.49% (p=0.000 n=9+10) Marshal/uint16-8 24.8ns ± 4% 7.4ns ± 2% -70.23% (p=0.000 n=10+9) Marshal/uint32-8 33.4ns ± 3% 7.1ns ± 5% -78.78% (p=0.000 n=8+10) Marshal/uint64-8 46.5ns ± 3% 8.5ns ± 4% -81.78% (p=0.000 n=9+10) Marshal/float32-8 33.7ns ± 7% 7.2ns ± 6% -78.73% (p=0.000 n=10+10) Marshal/float32#01-8 33.5ns ± 3% 7.1ns ± 5% -78.89% (p=0.000 n=10+10) Marshal/float32#02-8 33.4ns ± 5% 7.0ns ± 5% -78.99% (p=0.000 n=10+10) Marshal/float32#03-8 34.1ns ± 6% 7.2ns ± 4% -78.86% (p=0.000 n=10+10) Marshal/float64-8 47.3ns ± 3% 7.4ns ± 4% -84.38% (p=0.000 n=9+10) Marshal/float64#01-8 47.3ns ± 3% 7.4ns ± 6% -84.37% (p=0.000 n=8+10) Marshal/float64#02-8 46.9ns ± 5% 7.6ns ± 1% -83.87% (p=0.000 n=10+10) Marshal/float64#03-8 47.6ns ± 4% 7.3ns ± 4% -84.57% (p=0.000 n=9+10) Marshal/amqp.describedType-8 119ns ± 5% 65ns ± 5% -45.63% (p=0.000 n=10+9) Marshal/map[interface_{}]interface_{}-8 253ns ± 9% 79ns ± 4% -68.82% (p=0.000 n=9+10) Marshal/map[string]interface_{}-8 252ns ±11% 83ns ± 3% -67.08% (p=0.000 n=10+9) Marshal/amqp.ArrayUByte-8 38.5ns ± 4% 29.6ns ± 1% -23.25% (p=0.000 n=10+9) Marshal/[]int8-8 47.2ns ± 5% 24.9ns ± 5% -47.28% (p=0.000 n=10+9) Marshal/[]uint16-8 75.1ns ± 3% 24.1ns ± 5% -67.84% (p=0.000 n=10+10) Marshal/[]uint16#01-8 75.4ns ± 4% 24.4ns ± 5% -67.60% (p=0.000 n=10+10) Marshal/[]int16-8 75.0ns ± 6% 24.6ns ± 4% -67.26% (p=0.000 n=10+10) Marshal/[]int16#01-8 73.7ns ± 4% 23.9ns ± 7% -67.64% (p=0.000 n=10+10) Marshal/[]uint32-8 106ns ± 4% 24ns ± 2% -77.50% (p=0.000 n=10+9) Marshal/[]uint32#01-8 49.6ns ± 5% 26.7ns ± 6% -46.18% (p=0.000 n=10+10) Marshal/[]int32-8 105ns ± 3% 23ns ± 4% -77.70% (p=0.000 n=10+8) Marshal/[]int32#01-8 49.0ns ± 3% 27.1ns ± 5% -44.69% (p=0.000 n=9+9) Marshal/[]uint64-8 172ns ± 4% 24ns ± 3% -85.81% (p=0.000 n=10+10) Marshal/[]uint64#01-8 49.2ns ± 3% 26.7ns ± 2% -45.72% (p=0.000 n=10+8) Marshal/[]int64-8 172ns ± 2% 25ns ± 3% -85.57% (p=0.000 n=8+9) Marshal/[]int64#01-8 49.1ns ± 4% 27.2ns ± 4% -44.62% (p=0.000 n=10+10) Marshal/[]float32-8 90.6ns ± 3% 23.0ns ± 3% -74.58% (p=0.000 n=9+9) Marshal/[]float64-8 143ns ± 6% 23ns ± 9% -83.87% (p=0.000 n=10+10) Marshal/[]bool-8 44.0ns ± 4% 21.8ns ±10% -50.45% (p=0.000 n=10+10) Marshal/[]string-8 131ns ± 6% 43ns ± 3% -67.25% (p=0.000 n=10+10) Marshal/[]amqp.symbol-8 130ns ± 3% 41ns ± 2% -68.39% (p=0.000 n=10+10) Marshal/[][]uint8-8 127ns ± 4% 37ns ± 6% -71.02% (p=0.000 n=10+8) Marshal/[]time.Time-8 58.9ns ± 4% 19.5ns ± 4% -66.87% (p=0.000 n=10+10) Marshal/[]amqp.UUID-8 55.0ns ± 2% 20.2ns ± 5% -63.20% (p=0.000 n=10+10) Marshal/[]interface_{}-8 125ns ± 3% 43ns ± 5% -65.89% (p=0.000 n=8+10) Unmarshal/*amqp.performOpen-8 1.65µs ± 3% 0.91µs ±15% -44.61% (p=0.000 n=10+10) Unmarshal/*amqp.performBegin-8 1.33µs ± 4% 0.78µs ±14% -41.35% (p=0.000 n=10+10) Unmarshal/*amqp.performAttach-8 6.09µs ± 6% 3.80µs ±17% -37.52% (p=0.000 n=10+10) Unmarshal/amqp.role-8 215ns ±14% 58ns ± 8% -73.18% (p=0.000 n=10+10) Unmarshal/*amqp.unsettled-8 938ns ±20% 629ns ± 9% -33.01% (p=0.000 n=10+9) Unmarshal/*amqp.source-8 2.19µs ±11% 1.43µs ±25% -34.87% (p=0.000 n=10+10) Unmarshal/*amqp.target-8 1.29µs ± 5% 0.78µs ± 9% -39.50% (p=0.000 n=10+10) Unmarshal/*amqp.performFlow-8 1.82µs ± 1% 0.77µs ±15% -57.89% (p=0.000 n=10+10) Unmarshal/*amqp.performTransfer-8 1.71µs ± 2% 0.47µs ± 1% -72.26% (p=0.000 n=10+10) Unmarshal/*amqp.performDisposition-8 910ns ± 1% 242ns ± 1% -73.37% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach-8 1.49µs ± 3% 0.85µs ± 9% -42.86% (p=0.000 n=10+9) Unmarshal/*amqp.performDetach#01-8 1.93µs ± 7% 1.22µs ±13% -36.82% (p=0.000 n=10+10) Unmarshal/amqp.ErrorCondition-8 271ns ±15% 92ns ±14% -65.93% (p=0.000 n=10+10) Unmarshal/*amqp.Error-8 1.19µs ± 9% 0.76µs ±17% -36.36% (p=0.000 n=10+10) Unmarshal/*amqp.performEnd-8 1.38µs ± 4% 0.86µs ±23% -37.86% (p=0.000 n=10+10) Unmarshal/*amqp.performClose-8 1.32µs ± 2% 0.82µs ± 8% -38.12% (p=0.000 n=8+10) Unmarshal/*amqp.Message-8 4.66µs ± 4% 2.94µs ±16% -36.87% (p=0.000 n=10+10) Unmarshal/*amqp.MessageHeader-8 647ns ± 0% 206ns ± 1% -68.18% (p=0.000 n=8+9) Unmarshal/*amqp.MessageProperties-8 1.47µs ± 1% 0.53µs ± 1% -63.75% (p=0.000 n=10+10) Unmarshal/*amqp.stateReceived-8 385ns ± 2% 126ns ± 1% -67.23% (p=0.000 n=9+10) Unmarshal/*amqp.stateAccepted-8 255ns ±17% 94ns ± 3% -63.08% (p=0.000 n=10+10) Unmarshal/*amqp.stateRejected-8 1.40µs ± 4% 0.87µs ±11% -38.12% (p=0.000 n=9+10) Unmarshal/*amqp.stateReleased-8 251ns ± 9% 94ns ± 4% -62.81% (p=0.000 n=10+10) Unmarshal/*amqp.stateModified-8 1.01µs ± 8% 0.68µs ±21% -33.07% (p=0.000 n=9+10) Unmarshal/amqp.lifetimePolicy-8 203ns ± 7% 63ns ± 7% -68.74% (p=0.000 n=10+9) Unmarshal/amqp.SenderSettleMode-8 218ns ± 9% 57ns ±21% -73.84% (p=0.000 n=9+10) Unmarshal/amqp.ReceiverSettleMode-8 221ns ±11% 57ns ± 7% -74.38% (p=0.000 n=10+9) Unmarshal/*amqp.saslInit-8 551ns ± 1% 220ns ± 1% -60.10% (p=0.000 n=10+10) Unmarshal/*amqp.saslMechanisms-8 420ns ± 2% 187ns ± 1% -55.35% (p=0.000 n=10+9) Unmarshal/*amqp.saslOutcome-8 511ns ± 2% 187ns ± 2% -63.46% (p=0.000 n=10+9) Unmarshal/amqp.milliseconds-8 189ns ±22% 60ns ±17% -68.31% (p=0.000 n=10+10) Unmarshal/amqp.symbol-8 201ns ±12% 74ns ±21% -63.44% (p=0.000 n=10+10) Unmarshal/map[amqp.symbol]interface_{}-8 897ns ±31% 614ns ±16% -31.57% (p=0.000 n=10+10) Unmarshal/amqp.UUID-8 215ns ±16% 66ns ±12% -69.16% (p=0.000 n=10+10) Unmarshal/bool-8 174ns ±34% 56ns ±10% -67.75% (p=0.000 n=10+10) Unmarshal/int8-8 201ns ±26% 54ns ±17% -72.95% (p=0.000 n=10+10) Unmarshal/int8#01-8 175ns ±23% 57ns ±21% -67.47% (p=0.000 n=10+10) Unmarshal/int16-8 189ns ±15% 56ns ±16% -70.29% (p=0.000 n=10+10) Unmarshal/int16#01-8 185ns ±22% 55ns ±17% -70.31% (p=0.000 n=10+10) Unmarshal/int32-8 198ns ±13% 53ns ±11% -73.27% (p=0.000 n=10+9) Unmarshal/int32#01-8 200ns ±14% 55ns ±13% -72.32% (p=0.000 n=10+10) Unmarshal/int64-8 206ns ±16% 56ns ±19% -72.93% (p=0.000 n=10+10) Unmarshal/int64#01-8 190ns ±14% 52ns ±12% -72.48% (p=0.000 n=10+9) Unmarshal/uint8-8 188ns ±11% 55ns ±13% -70.70% (p=0.000 n=10+10) Unmarshal/uint16-8 197ns ±12% 55ns ±11% -72.16% (p=0.000 n=10+10) Unmarshal/uint32-8 187ns ±14% 57ns ±10% -69.62% (p=0.000 n=8+9) Unmarshal/uint64-8 174ns ±23% 54ns ±27% -68.90% (p=0.000 n=10+10) Unmarshal/float32-8 198ns ±24% 55ns ±20% -72.17% (p=0.000 n=10+10) Unmarshal/float32#01-8 187ns ±15% 55ns ±12% -70.82% (p=0.000 n=10+10) Unmarshal/float32#02-8 186ns ±19% 56ns ±13% -69.76% (p=0.000 n=10+10) Unmarshal/float32#03-8 184ns ±12% 52ns ±13% -71.93% (p=0.000 n=10+10) Unmarshal/float64-8 179ns ± 7% 54ns ± 7% -69.55% (p=0.000 n=9+10) Unmarshal/float64#01-8 188ns ±17% 54ns ±16% -71.39% (p=0.000 n=10+10) Unmarshal/float64#02-8 186ns ±15% 55ns ±19% -70.35% (p=0.000 n=10+10) Unmarshal/float64#03-8 185ns ±13% 56ns ±21% -69.69% (p=0.000 n=10+10) Unmarshal/amqp.describedType-8 413ns ±12% 203ns ±11% -50.91% (p=0.000 n=10+10) Unmarshal/map[interface_{}]interface_{}-8 774ns ±22% 618ns ±17% -20.15% (p=0.000 n=10+10) Unmarshal/map[string]interface_{}-8 769ns ±35% 591ns ±17% -23.16% (p=0.015 n=10+10) Unmarshal/amqp.ArrayUByte-8 203ns ±16% 88ns ±10% -56.70% (p=0.000 n=10+10) Unmarshal/[]int8-8 205ns ±12% 58ns ±10% -71.96% (p=0.000 n=9+9) Unmarshal/[]uint16-8 194ns ±14% 63ns ±18% -67.66% (p=0.000 n=10+10) Unmarshal/[]uint16#01-8 194ns ±20% 62ns ±12% -68.16% (p=0.000 n=10+10) Unmarshal/[]int16-8 200ns ±12% 61ns ± 6% -69.48% (p=0.000 n=10+9) Unmarshal/[]int16#01-8 200ns ± 7% 64ns ±14% -68.04% (p=0.000 n=10+10) Unmarshal/[]uint32-8 193ns ±16% 61ns ±10% -68.53% (p=0.000 n=10+10) Unmarshal/[]uint32#01-8 200ns ±20% 58ns ±11% -70.86% (p=0.000 n=10+10) Unmarshal/[]int32-8 201ns ±20% 64ns ±15% -68.14% (p=0.000 n=10+10) Unmarshal/[]int32#01-8 187ns ±14% 60ns ±17% -67.67% (p=0.000 n=9+10) Unmarshal/[]uint64-8 182ns ±12% 63ns ±12% -65.47% (p=0.000 n=10+10) Unmarshal/[]uint64#01-8 207ns ± 8% 60ns ±16% -70.82% (p=0.000 n=9+10) Unmarshal/[]int64-8 202ns ±20% 64ns ±10% -68.57% (p=0.000 n=10+10) Unmarshal/[]int64#01-8 197ns ±19% 56ns ± 9% -71.50% (p=0.000 n=10+9) Unmarshal/[]float32-8 197ns ±14% 61ns ±16% -68.78% (p=0.000 n=10+9) Unmarshal/[]float64-8 202ns ±16% 64ns ± 7% -68.32% (p=0.000 n=10+9) Unmarshal/[]bool-8 195ns ±15% 61ns ± 6% -68.76% (p=0.000 n=10+9) Unmarshal/[]string-8 249ns ±10% 109ns ± 5% -56.19% (p=0.000 n=10+10) Unmarshal/[]amqp.symbol-8 253ns ± 9% 110ns ± 5% -56.60% (p=0.000 n=10+10) Unmarshal/[][]uint8-8 285ns ± 3% 139ns ± 6% -51.29% (p=0.000 n=8+10) Unmarshal/[]time.Time-8 192ns ±15% 61ns ± 6% -68.44% (p=0.000 n=10+10) Unmarshal/[]amqp.UUID-8 192ns ±12% 61ns ±12% -67.98% (p=0.000 n=10+10) Unmarshal/[]interface_{}-8 296ns ± 8% 142ns ± 4% -51.92% (p=0.000 n=9+10) name old alloc/op new alloc/op delta FrameMarshal/transfer-8 0.00B 0.00B ~ (all equal) FrameUnmarshal/transfer-8 312B ± 0% 232B ± 0% -25.64% (p=0.000 n=10+10) Marshal/*amqp.performOpen-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performBegin-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performAttach-8 576B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.role-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.unsettled-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.source-8 230B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.target-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performFlow-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performTransfer-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.performDisposition-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.performDetach-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performDetach#01-8 617B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.ErrorCondition-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.Error-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performEnd-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.performClose-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.Message-8 464B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageHeader-8 4.00B ± 0% 0.00B -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageProperties-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateReceived-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateAccepted-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateRejected-8 131B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.stateReleased-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.stateModified-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.lifetimePolicy-8 0.00B 0.00B ~ (all equal) Marshal/amqp.SenderSettleMode-8 0.00B 0.00B ~ (all equal) Marshal/amqp.ReceiverSettleMode-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.saslInit-8 0.00B 0.00B ~ (all equal) Marshal/*amqp.saslMechanisms-8 32.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/*amqp.saslOutcome-8 32.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/amqp.milliseconds-8 4.00B ± 0% 0.00B -100.00% (p=0.000 n=10+10) Marshal/amqp.symbol-8 0.00B 0.00B ~ (all equal) Marshal/map[amqp.symbol]interface_{}-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.UUID-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/bool-8 0.00B 0.00B ~ (all equal) Marshal/int8-8 0.00B 0.00B ~ (all equal) Marshal/int8#01-8 0.00B 0.00B ~ (all equal) Marshal/int16-8 0.00B 0.00B ~ (all equal) Marshal/int16#01-8 0.00B 0.00B ~ (all equal) Marshal/int32-8 0.00B 0.00B ~ (all equal) Marshal/int32#01-8 0.00B 0.00B ~ (all equal) Marshal/int64-8 0.00B 0.00B ~ (all equal) Marshal/int64#01-8 0.00B 0.00B ~ (all equal) Marshal/uint8-8 0.00B 0.00B ~ (all equal) Marshal/uint16-8 0.00B 0.00B ~ (all equal) Marshal/uint32-8 0.00B 0.00B ~ (all equal) Marshal/uint64-8 0.00B 0.00B ~ (all equal) Marshal/float32-8 0.00B 0.00B ~ (all equal) Marshal/float32#01-8 0.00B 0.00B ~ (all equal) Marshal/float32#02-8 0.00B 0.00B ~ (all equal) Marshal/float32#03-8 0.00B 0.00B ~ (all equal) Marshal/float64-8 0.00B 0.00B ~ (all equal) Marshal/float64#01-8 0.00B 0.00B ~ (all equal) Marshal/float64#02-8 0.00B 0.00B ~ (all equal) Marshal/float64#03-8 0.00B 0.00B ~ (all equal) Marshal/amqp.describedType-8 0.00B 0.00B ~ (all equal) Marshal/map[interface_{}]interface_{}-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/map[string]interface_{}-8 115B ± 0% 0B -100.00% (p=0.000 n=10+10) Marshal/amqp.ArrayUByte-8 0.00B 0.00B ~ (all equal) Marshal/[]int8-8 0.00B 0.00B ~ (all equal) Marshal/[]uint16-8 0.00B 0.00B ~ (all equal) Marshal/[]uint16#01-8 0.00B 0.00B ~ (all equal) Marshal/[]int16-8 0.00B 0.00B ~ (all equal) Marshal/[]int16#01-8 0.00B 0.00B ~ (all equal) Marshal/[]uint32-8 0.00B 0.00B ~ (all equal) Marshal/[]uint32#01-8 0.00B 0.00B ~ (all equal) Marshal/[]int32-8 0.00B 0.00B ~ (all equal) Marshal/[]int32#01-8 0.00B 0.00B ~ (all equal) Marshal/[]uint64-8 0.00B 0.00B ~ (all equal) Marshal/[]uint64#01-8 0.00B 0.00B ~ (all equal) Marshal/[]int64-8 0.00B 0.00B ~ (all equal) Marshal/[]int64#01-8 0.00B 0.00B ~ (all equal) Marshal/[]float32-8 0.00B 0.00B ~ (all equal) Marshal/[]float64-8 0.00B 0.00B ~ (all equal) Marshal/[]bool-8 0.00B 0.00B ~ (all equal) Marshal/[]string-8 0.00B 0.00B ~ (all equal) Marshal/[]amqp.symbol-8 0.00B 0.00B ~ (all equal) Marshal/[][]uint8-8 0.00B 0.00B ~ (all equal) Marshal/[]time.Time-8 0.00B 0.00B ~ (all equal) Marshal/[]amqp.UUID-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) Marshal/[]interface_{}-8 0.00B 0.00B ~ (all equal) Unmarshal/*amqp.performOpen-8 544B ± 0% 464B ± 0% -14.71% (p=0.000 n=10+10) Unmarshal/*amqp.performBegin-8 496B ± 0% 416B ± 0% -16.13% (p=0.000 n=10+10) Unmarshal/*amqp.performAttach-8 2.08kB ± 0% 2.00kB ± 0% -3.85% (p=0.000 n=10+10) Unmarshal/amqp.role-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.unsettled-8 480B ± 0% 400B ± 0% -16.67% (p=0.000 n=10+10) Unmarshal/*amqp.source-8 928B ± 0% 848B ± 0% -8.62% (p=0.000 n=10+10) Unmarshal/*amqp.target-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performFlow-8 464B ± 0% 400B ± 0% -13.79% (p=0.000 n=10+10) Unmarshal/*amqp.performTransfer-8 168B ± 0% 96B ± 0% -42.86% (p=0.000 n=10+10) Unmarshal/*amqp.performDisposition-8 112B ± 0% 36B ± 0% -67.86% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach#01-8 728B ± 0% 648B ± 0% -10.99% (p=0.000 n=10+10) Unmarshal/amqp.ErrorCondition-8 128B ± 0% 48B ± 0% -62.50% (p=0.000 n=10+10) Unmarshal/*amqp.Error-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performEnd-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.performClose-8 512B ± 0% 432B ± 0% -15.62% (p=0.000 n=10+10) Unmarshal/*amqp.Message-8 1.73kB ± 0% 1.65kB ± 0% -4.63% (p=0.000 n=10+10) Unmarshal/*amqp.MessageHeader-8 128B ± 0% 48B ± 0% -62.50% (p=0.000 n=10+10) Unmarshal/*amqp.MessageProperties-8 208B ± 0% 128B ± 0% -38.46% (p=0.000 n=10+10) Unmarshal/*amqp.stateReceived-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.stateAccepted-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.stateRejected-8 517B ± 0% 437B ± 0% -15.47% (p=0.000 n=10+10) Unmarshal/*amqp.stateReleased-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.stateModified-8 480B ± 0% 400B ± 0% -16.67% (p=0.000 n=10+10) Unmarshal/amqp.lifetimePolicy-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.SenderSettleMode-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.ReceiverSettleMode-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/*amqp.saslInit-8 134B ± 0% 54B ± 0% -59.70% (p=0.000 n=10+10) Unmarshal/*amqp.saslMechanisms-8 121B ± 0% 41B ± 0% -66.12% (p=0.000 n=10+10) Unmarshal/*amqp.saslOutcome-8 144B ± 0% 64B ± 0% -55.56% (p=0.000 n=10+10) Unmarshal/amqp.milliseconds-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.symbol-8 120B ± 0% 40B ± 0% -66.67% (p=0.000 n=10+10) Unmarshal/map[amqp.symbol]interface_{}-8 500B ± 0% 420B ± 0% -16.00% (p=0.000 n=10+10) Unmarshal/amqp.UUID-8 128B ± 0% 32B ± 0% -75.00% (p=0.000 n=10+10) Unmarshal/bool-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int8-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int8#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int16#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/int64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint8-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/uint64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32#02-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float32#03-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64#02-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/float64#03-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/amqp.describedType-8 184B ± 0% 104B ± 0% -43.48% (p=0.000 n=10+10) Unmarshal/map[interface_{}]interface_{}-8 500B ± 0% 420B ± 0% -16.00% (p=0.000 n=10+10) Unmarshal/map[string]interface_{}-8 500B ± 0% 420B ± 0% -16.00% (p=0.000 n=10+10) Unmarshal/amqp.ArrayUByte-8 112B ± 0% 40B ± 0% -64.29% (p=0.000 n=10+10) Unmarshal/[]int8-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint16#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int16-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int16#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int32#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]uint64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]int64#01-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]float32-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]float64-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]bool-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]string-8 121B ± 0% 41B ± 0% -66.12% (p=0.000 n=10+10) Unmarshal/[]amqp.symbol-8 121B ± 0% 41B ± 0% -66.12% (p=0.000 n=10+10) Unmarshal/[][]uint8-8 136B ± 0% 56B ± 0% -58.82% (p=0.000 n=10+10) Unmarshal/[]time.Time-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]amqp.UUID-8 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) Unmarshal/[]interface_{}-8 136B ± 0% 56B ± 0% -58.82% (p=0.000 n=10+10) name old allocs/op new allocs/op delta FrameMarshal/transfer-8 0.00 0.00 ~ (all equal) FrameUnmarshal/transfer-8 8.00 ± 0% 8.00 ± 0% ~ (all equal) Marshal/*amqp.performOpen-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performBegin-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performAttach-8 10.0 ± 0% 0.0 -100.00% (p=0.000 n=10+10) Marshal/amqp.role-8 0.00 0.00 ~ (all equal) Marshal/*amqp.unsettled-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.source-8 4.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.target-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performFlow-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performTransfer-8 0.00 0.00 ~ (all equal) Marshal/*amqp.performDisposition-8 0.00 0.00 ~ (all equal) Marshal/*amqp.performDetach-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performDetach#01-8 4.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.ErrorCondition-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.Error-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performEnd-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.performClose-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.Message-8 9.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageHeader-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.MessageProperties-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateReceived-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateAccepted-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateRejected-8 3.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.stateReleased-8 0.00 0.00 ~ (all equal) Marshal/*amqp.stateModified-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.lifetimePolicy-8 0.00 0.00 ~ (all equal) Marshal/amqp.SenderSettleMode-8 0.00 0.00 ~ (all equal) Marshal/amqp.ReceiverSettleMode-8 0.00 0.00 ~ (all equal) Marshal/*amqp.saslInit-8 0.00 0.00 ~ (all equal) Marshal/*amqp.saslMechanisms-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/*amqp.saslOutcome-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.milliseconds-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.symbol-8 0.00 0.00 ~ (all equal) Marshal/map[amqp.symbol]interface_{}-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.UUID-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/bool-8 0.00 0.00 ~ (all equal) Marshal/int8-8 0.00 0.00 ~ (all equal) Marshal/int8#01-8 0.00 0.00 ~ (all equal) Marshal/int16-8 0.00 0.00 ~ (all equal) Marshal/int16#01-8 0.00 0.00 ~ (all equal) Marshal/int32-8 0.00 0.00 ~ (all equal) Marshal/int32#01-8 0.00 0.00 ~ (all equal) Marshal/int64-8 0.00 0.00 ~ (all equal) Marshal/int64#01-8 0.00 0.00 ~ (all equal) Marshal/uint8-8 0.00 0.00 ~ (all equal) Marshal/uint16-8 0.00 0.00 ~ (all equal) Marshal/uint32-8 0.00 0.00 ~ (all equal) Marshal/uint64-8 0.00 0.00 ~ (all equal) Marshal/float32-8 0.00 0.00 ~ (all equal) Marshal/float32#01-8 0.00 0.00 ~ (all equal) Marshal/float32#02-8 0.00 0.00 ~ (all equal) Marshal/float32#03-8 0.00 0.00 ~ (all equal) Marshal/float64-8 0.00 0.00 ~ (all equal) Marshal/float64#01-8 0.00 0.00 ~ (all equal) Marshal/float64#02-8 0.00 0.00 ~ (all equal) Marshal/float64#03-8 0.00 0.00 ~ (all equal) Marshal/amqp.describedType-8 0.00 0.00 ~ (all equal) Marshal/map[interface_{}]interface_{}-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/map[string]interface_{}-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/amqp.ArrayUByte-8 0.00 0.00 ~ (all equal) Marshal/[]int8-8 0.00 0.00 ~ (all equal) Marshal/[]uint16-8 0.00 0.00 ~ (all equal) Marshal/[]uint16#01-8 0.00 0.00 ~ (all equal) Marshal/[]int16-8 0.00 0.00 ~ (all equal) Marshal/[]int16#01-8 0.00 0.00 ~ (all equal) Marshal/[]uint32-8 0.00 0.00 ~ (all equal) Marshal/[]uint32#01-8 0.00 0.00 ~ (all equal) Marshal/[]int32-8 0.00 0.00 ~ (all equal) Marshal/[]int32#01-8 0.00 0.00 ~ (all equal) Marshal/[]uint64-8 0.00 0.00 ~ (all equal) Marshal/[]uint64#01-8 0.00 0.00 ~ (all equal) Marshal/[]int64-8 0.00 0.00 ~ (all equal) Marshal/[]int64#01-8 0.00 0.00 ~ (all equal) Marshal/[]float32-8 0.00 0.00 ~ (all equal) Marshal/[]float64-8 0.00 0.00 ~ (all equal) Marshal/[]bool-8 0.00 0.00 ~ (all equal) Marshal/[]string-8 0.00 0.00 ~ (all equal) Marshal/[]amqp.symbol-8 0.00 0.00 ~ (all equal) Marshal/[][]uint8-8 0.00 0.00 ~ (all equal) Marshal/[]time.Time-8 0.00 0.00 ~ (all equal) Marshal/[]amqp.UUID-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) Marshal/[]interface_{}-8 0.00 0.00 ~ (all equal) Unmarshal/*amqp.performOpen-8 13.0 ± 0% 13.0 ± 0% ~ (all equal) Unmarshal/*amqp.performBegin-8 8.00 ± 0% 8.00 ± 0% ~ (all equal) Unmarshal/*amqp.performAttach-8 33.0 ± 0% 33.0 ± 0% ~ (all equal) Unmarshal/amqp.role-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.unsettled-8 5.00 ± 0% 5.00 ± 0% ~ (all equal) Unmarshal/*amqp.source-8 15.0 ± 0% 15.0 ± 0% ~ (all equal) Unmarshal/*amqp.target-8 8.00 ± 0% 8.00 ± 0% ~ (all equal) Unmarshal/*amqp.performFlow-8 5.00 ± 0% 10.00 ± 0% +100.00% (p=0.000 n=10+10) Unmarshal/*amqp.performTransfer-8 4.00 ± 0% 6.00 ± 0% +50.00% (p=0.000 n=10+10) Unmarshal/*amqp.performDisposition-8 1.00 ± 0% 2.00 ± 0% +100.00% (p=0.000 n=10+10) Unmarshal/*amqp.performDetach-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.performDetach#01-8 15.0 ± 0% 15.0 ± 0% ~ (all equal) Unmarshal/amqp.ErrorCondition-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/*amqp.Error-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.performEnd-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.performClose-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.Message-8 33.0 ± 0% 33.0 ± 0% ~ (all equal) Unmarshal/*amqp.MessageHeader-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/*amqp.MessageProperties-8 12.0 ± 0% 12.0 ± 0% ~ (all equal) Unmarshal/*amqp.stateReceived-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.stateAccepted-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.stateRejected-8 10.0 ± 0% 10.0 ± 0% ~ (all equal) Unmarshal/*amqp.stateReleased-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.stateModified-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/amqp.lifetimePolicy-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.SenderSettleMode-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.ReceiverSettleMode-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/*amqp.saslInit-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/*amqp.saslMechanisms-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/*amqp.saslOutcome-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/amqp.milliseconds-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.symbol-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) Unmarshal/map[amqp.symbol]interface_{}-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/amqp.UUID-8 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) Unmarshal/bool-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int8-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int8#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int16#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/int64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint8-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/uint64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32#02-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float32#03-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64#02-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/float64#03-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/amqp.describedType-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/map[interface_{}]interface_{}-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/map[string]interface_{}-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) Unmarshal/amqp.ArrayUByte-8 1.00 ± 0% 2.00 ± 0% +100.00% (p=0.000 n=10+10) Unmarshal/[]int8-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint16#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int16-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int16#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int32#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]uint64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]int64#01-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]float32-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]float64-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]bool-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]string-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/[]amqp.symbol-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/[][]uint8-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) Unmarshal/[]time.Time-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]amqp.UUID-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Unmarshal/[]interface_{}-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) ```
2018-02-03 22:54:49 +03:00
if !ok {
c.connErr <- io.EOF
return
}
parsedBody, err := frames.ParseBody(buffer.New(b))
2017-04-27 06:35:29 +03:00
if err != nil {
c.connErr <- err
2017-04-27 06:35:29 +03:00
return
}
// send to mux
2017-04-27 06:35:29 +03:00
select {
case <-c.Done:
2017-04-27 06:35:29 +03:00
return
case c.rxFrame <- frames.Frame{Channel: currentHeader.Channel, Body: parsedBody}:
2017-04-27 06:35:29 +03:00
}
2017-04-01 23:00:36 +03:00
}
}
func (c *conn) connWriter() {
defer close(c.txDone)
// disable write timeout
if c.connectTimeout != 0 {
c.connectTimeout = 0
_ = c.net.SetWriteDeadline(time.Time{})
}
var (
// keepalives are sent at a rate of 1/2 idle timeout
keepaliveInterval = c.peerIdleTimeout / 2
// 0 disables keepalives
keepalivesEnabled = keepaliveInterval > 0
// set if enable, nil if not; nil channels block forever
keepalive <-chan time.Time
)
if keepalivesEnabled {
ticker := time.NewTicker(keepaliveInterval)
defer ticker.Stop()
keepalive = ticker.C
}
var err error
for {
if err != nil {
c.connErr <- err
return
}
select {
// frame write request
case fr := <-c.txFrame:
err = c.writeFrame(fr)
if err == nil && fr.Done != nil {
close(fr.Done)
}
// keepalive timer
case <-keepalive:
debug(3, "sending keep-alive frame")
_, err = c.net.Write(keepaliveFrame)
// It would be slightly more efficient in terms of network
// resources to reset the timer each time a frame is sent.
// However, keepalives are small (8 bytes) and the interval
// is usually on the order of minutes. It does not seem
// worth it to add extra operations in the write path to
// avoid. (To properly reset a timer it needs to be stopped,
// possibly drained, then reset.)
// connection complete
case <-c.Done:
// send close
cls := &frames.PerformClose{}
debug(1, "TX (connWriter): %s", cls)
_ = c.writeFrame(frames.Frame{
Type: frameTypeAMQP,
Body: cls,
})
return
}
}
}
// writeFrame writes a frame to the network.
// used externally by SASL only.
func (c *conn) writeFrame(fr frames.Frame) error {
if c.connectTimeout != 0 {
2018-02-17 19:24:03 +03:00
_ = c.net.SetWriteDeadline(time.Now().Add(c.connectTimeout))
}
2017-05-07 02:57:27 +03:00
// writeFrame into txBuf
c.txBuf.Reset()
err := writeFrame(&c.txBuf, fr)
if err != nil {
return err
}
// validate the frame isn't exceeding peer's max frame size
requiredFrameSize := c.txBuf.Len()
if uint64(requiredFrameSize) > uint64(c.PeerMaxFrameSize) {
return fmt.Errorf("%T frame size %d larger than peer's max frame size %d", fr, requiredFrameSize, c.PeerMaxFrameSize)
}
2017-05-07 02:57:27 +03:00
// write to network
_, err = c.net.Write(c.txBuf.Bytes())
return err
}
2017-05-07 02:57:27 +03:00
// writeProtoHeader writes an AMQP protocol header to the
// network
func (c *conn) writeProtoHeader(pID protoID) error {
if c.connectTimeout != 0 {
2018-02-17 19:24:03 +03:00
_ = c.net.SetWriteDeadline(time.Now().Add(c.connectTimeout))
}
_, err := c.net.Write([]byte{'A', 'M', 'Q', 'P', byte(pID), 1, 0, 0})
return err
}
// keepaliveFrame is an AMQP frame with no body, used for keepalives
var keepaliveFrame = []byte{0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00}
// SendFrame is used by sessions and links to send frames across the network.
func (c *conn) SendFrame(fr frames.Frame) error {
select {
case c.txFrame <- fr:
return nil
case <-c.Done:
return c.Err()
}
}
// stateFunc is a state in a state machine.
//
// The state is advanced by returning the next state.
// The state machine concludes when nil is returned.
type stateFunc func() stateFunc
// negotiateProto determines which proto to negotiate next.
// used externally by SASL only.
func (c *conn) negotiateProto() stateFunc {
// in the order each must be negotiated
2017-04-01 23:00:36 +03:00
switch {
case c.tlsNegotiation && !c.tlsComplete:
2017-04-23 21:01:44 +03:00
return c.exchangeProtoHeader(protoTLS)
2017-04-01 23:00:36 +03:00
case c.saslHandlers != nil && !c.saslComplete:
2017-04-23 21:01:44 +03:00
return c.exchangeProtoHeader(protoSASL)
2017-04-01 23:00:36 +03:00
default:
2017-04-23 21:01:44 +03:00
return c.exchangeProtoHeader(protoAMQP)
2017-04-01 23:00:36 +03:00
}
}
type protoID uint8
// protocol IDs received in protoHeaders
2017-04-01 23:00:36 +03:00
const (
protoAMQP protoID = 0x0
protoTLS protoID = 0x2
protoSASL protoID = 0x3
2017-04-01 23:00:36 +03:00
)
2017-04-30 02:38:15 +03:00
// exchangeProtoHeader performs the round trip exchange of protocol
// headers, validation, and returns the protoID specific next state.
func (c *conn) exchangeProtoHeader(pID protoID) stateFunc {
// write the proto header
c.err = c.writeProtoHeader(pID)
if c.err != nil {
return nil
}
2017-04-01 23:00:36 +03:00
// read response header
p, err := c.readProtoHeader()
if err != nil {
c.err = err
2017-04-01 23:00:36 +03:00
return nil
}
if pID != p.ProtoID {
c.err = fmt.Errorf("unexpected protocol header %#00x, expected %#00x", p.ProtoID, pID)
2017-04-01 23:00:36 +03:00
return nil
}
// go to the proto specific state
switch pID {
2017-04-23 21:01:44 +03:00
case protoAMQP:
2017-04-30 02:38:15 +03:00
return c.openAMQP
2017-04-23 21:01:44 +03:00
case protoTLS:
2017-04-30 02:38:15 +03:00
return c.startTLS
2017-04-23 21:01:44 +03:00
case protoSASL:
2017-04-30 02:38:15 +03:00
return c.negotiateSASL
2017-04-01 23:00:36 +03:00
default:
c.err = fmt.Errorf("unknown protocol ID %#02x", p.ProtoID)
2017-04-01 23:00:36 +03:00
return nil
}
}
2017-05-07 02:57:27 +03:00
// readProtoHeader reads a protocol header packet from c.rxProto.
func (c *conn) readProtoHeader() (protoHeader, error) {
var deadline <-chan time.Time
if c.connectTimeout != 0 {
deadline = time.After(c.connectTimeout)
}
var p protoHeader
select {
case p = <-c.rxProto:
return p, nil
case err := <-c.connErr:
return p, err
case fr := <-c.rxFrame:
return p, fmt.Errorf("readProtoHeader: unexpected frame %#v", fr)
case <-deadline:
return p, errors.New("amqp: timeout waiting for response")
}
}
// startTLS wraps the conn with TLS and returns to Client.negotiateProto
func (c *conn) startTLS() stateFunc {
c.initTLSConfig()
2017-04-30 05:33:03 +03:00
done := make(chan struct{})
2017-04-30 05:33:03 +03:00
// this function will be executed by connReader
c.connReaderRun <- func() {
2018-02-17 19:24:03 +03:00
_ = c.net.SetReadDeadline(time.Time{}) // clear timeout
// wrap existing net.Conn and perform TLS handshake
tlsConn := tls.Client(c.net, c.tlsConfig)
if c.connectTimeout != 0 {
2018-02-17 19:24:03 +03:00
_ = tlsConn.SetWriteDeadline(time.Now().Add(c.connectTimeout))
}
c.err = tlsConn.Handshake()
// swap net.Conn
c.net = tlsConn
c.tlsComplete = true
close(done)
}
// set deadline to interrupt connReader
2018-02-17 19:24:03 +03:00
_ = c.net.SetReadDeadline(time.Time{}.Add(1))
<-done
2017-04-30 05:33:03 +03:00
if c.err != nil {
return nil
}
// go to next protocol
2017-04-23 04:32:50 +03:00
return c.negotiateProto
}
2017-04-30 02:38:15 +03:00
// openAMQP round trips the AMQP open performative
func (c *conn) openAMQP() stateFunc {
// send open frame
open := &frames.PerformOpen{
ContainerID: c.containerID,
Hostname: c.hostname,
MaxFrameSize: c.maxFrameSize,
ChannelMax: c.channelMax,
IdleTimeout: c.idleTimeout / 2, // per spec, advertise half our idle timeout
Properties: c.properties,
}
debug(1, "TX (openAMQP): %s", open)
c.err = c.writeFrame(frames.Frame{
Type: frameTypeAMQP,
Body: open,
Channel: 0,
})
if c.err != nil {
return nil
}
2017-04-01 23:00:36 +03:00
// get the response
2017-04-24 06:24:12 +03:00
fr, err := c.readFrame()
2017-04-01 23:00:36 +03:00
if err != nil {
2017-04-24 06:24:12 +03:00
c.err = err
2017-04-01 23:00:36 +03:00
return nil
}
o, ok := fr.Body.(*frames.PerformOpen)
2017-04-24 06:24:12 +03:00
if !ok {
c.err = fmt.Errorf("openAMQP: unexpected frame type %T", fr.Body)
2017-04-27 06:35:29 +03:00
return nil
2017-04-01 23:00:36 +03:00
}
debug(1, "RX (openAMQP): %s", o)
2017-04-01 23:00:36 +03:00
// update peer settings
2017-04-27 06:35:29 +03:00
if o.MaxFrameSize > 0 {
c.PeerMaxFrameSize = o.MaxFrameSize
2017-04-27 06:35:29 +03:00
}
2017-04-23 21:01:44 +03:00
if o.IdleTimeout > 0 {
// TODO: reject very small idle timeouts
2017-04-30 02:38:15 +03:00
c.peerIdleTimeout = o.IdleTimeout
2017-04-17 06:39:31 +03:00
}
2017-04-01 23:00:36 +03:00
if o.ChannelMax < c.channelMax {
c.channelMax = o.ChannelMax
}
// connection established, exit state machine
2017-04-01 23:00:36 +03:00
return nil
}
2017-04-30 02:38:15 +03:00
// negotiateSASL returns the SASL handler for the first matched
// mechanism specified by the server
func (c *conn) negotiateSASL() stateFunc {
// read mechanisms frame
2017-04-24 06:24:12 +03:00
fr, err := c.readFrame()
2017-04-01 23:00:36 +03:00
if err != nil {
c.err = err
return nil
}
sm, ok := fr.Body.(*frames.SASLMechanisms)
2017-04-24 06:24:12 +03:00
if !ok {
c.err = fmt.Errorf("negotiateSASL: unexpected frame type %T", fr.Body)
2017-04-01 23:00:36 +03:00
return nil
}
debug(1, "RX (negotiateSASL): %s", sm)
2017-04-01 23:00:36 +03:00
// return first match in c.saslHandlers based on order received
2017-04-01 23:00:36 +03:00
for _, mech := range sm.Mechanisms {
if state, ok := c.saslHandlers[mech]; ok {
return state
}
}
// no match
c.err = fmt.Errorf("no supported auth mechanism (%v)", sm.Mechanisms) // TODO: send "auth not supported" frame?
2017-04-01 23:00:36 +03:00
return nil
}
// saslOutcome processes the SASL outcome frame and return Client.negotiateProto
2017-04-30 02:38:15 +03:00
// on success.
//
// SASL handlers return this stateFunc when the mechanism specific negotiation
// has completed.
// used externally by SASL only.
func (c *conn) saslOutcome() stateFunc {
// read outcome frame
2017-04-24 06:24:12 +03:00
fr, err := c.readFrame()
2017-04-01 23:00:36 +03:00
if err != nil {
c.err = err
return nil
}
so, ok := fr.Body.(*frames.SASLOutcome)
2017-04-24 06:24:12 +03:00
if !ok {
c.err = fmt.Errorf("saslOutcome: unexpected frame type %T", fr.Body)
2017-04-27 06:35:29 +03:00
return nil
2017-04-01 23:00:36 +03:00
}
debug(1, "RX (saslOutcome): %s", so)
2017-04-01 23:00:36 +03:00
// check if auth succeeded
if so.Code != encoding.CodeSASLOK {
c.err = fmt.Errorf("SASL PLAIN auth failed with code %#00x: %s", so.Code, so.AdditionalData) // implement Stringer for so.Code
2017-04-01 23:00:36 +03:00
return nil
}
// return to c.negotiateProto
2017-04-01 23:00:36 +03:00
c.saslComplete = true
return c.negotiateProto
}
2017-04-24 06:24:12 +03:00
2017-04-30 02:38:15 +03:00
// readFrame is used during connection establishment to read a single frame.
//
2017-05-07 02:57:27 +03:00
// After setup, conn.mux handles incoming frames.
// used externally by SASL only.
func (c *conn) readFrame() (frames.Frame, error) {
var deadline <-chan time.Time
if c.connectTimeout != 0 {
deadline = time.After(c.connectTimeout)
}
var fr frames.Frame
2017-04-24 06:24:12 +03:00
select {
case fr = <-c.rxFrame:
return fr, nil
case err := <-c.connErr:
2017-04-24 06:24:12 +03:00
return fr, err
case p := <-c.rxProto:
return fr, fmt.Errorf("unexpected protocol header %#v", p)
case <-deadline:
return fr, errors.New("amqp: timeout waiting for response")
2017-04-24 06:24:12 +03:00
}
}
type protoHeader struct {
ProtoID protoID
Major uint8
Minor uint8
Revision uint8
}
// parseProtoHeader reads the proto header from r and returns the results
//
// An error is returned if the protocol is not "AMQP" or if the version is not 1.0.0.
func parseProtoHeader(r *buffer.Buffer) (protoHeader, error) {
const protoHeaderSize = 8
buf, ok := r.Next(protoHeaderSize)
if !ok {
return protoHeader{}, errors.New("invalid protoHeader")
}
_ = buf[7]
if !bytes.Equal(buf[:4], []byte{'A', 'M', 'Q', 'P'}) {
return protoHeader{}, fmt.Errorf("unexpected protocol %q", buf[:4])
}
p := protoHeader{
ProtoID: protoID(buf[4]),
Major: buf[5],
Minor: buf[6],
Revision: buf[7],
}
if p.Major != 1 || p.Minor != 0 || p.Revision != 0 {
return p, fmt.Errorf("unexpected protocol version %d.%d.%d", p.Major, p.Minor, p.Revision)
}
return p, nil
}
// writesFrame encodes fr into buf.
// split out from conn.WriteFrame for testing purposes.
func writeFrame(buf *buffer.Buffer, fr frames.Frame) error {
// write header
buf.Append([]byte{
0, 0, 0, 0, // size, overwrite later
2, // doff, see frameHeader.DataOffset comment
fr.Type, // frame type
})
buf.AppendUint16(fr.Channel) // channel
// write AMQP frame body
err := encoding.Marshal(buf, fr.Body)
if err != nil {
return err
}
// validate size
if uint(buf.Len()) > math.MaxUint32 {
return errors.New("frame too large")
}
// retrieve raw bytes
bufBytes := buf.Bytes()
// write correct size
binary.BigEndian.PutUint32(bufBytes, uint32(len(bufBytes)))
return nil
}