moving UDP payload size to config option, improve throughput performance

moving UDP payload size to optional config choice to imporove throughput performance
pull/5201/head
Sebastian Borza 2015-12-22 08:58:11 -05:00
parent 308cab0a52
commit 3bf5d9c969
4 changed files with 27 additions and 5 deletions

View File

@ -330,6 +330,7 @@ reporting-disabled = false
# batch-pending = 5 # number of batches that may be pending in memory
# batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit
# read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max.
# udp-payload-size = 1500 # set the expected UDP payload size, default: 65536
###
### [continuous_queries]

View File

@ -31,6 +31,24 @@ const (
// Linux: sudo sysctl -w net.core.rmem_max=<read-buffer>
// BSD/Darwin: sudo sysctl -w kern.ipc.maxsockbuf=<read-buffer>
DefaultReadBuffer = 0
// DefaultUDPPayloadSize sets the default value of the incoming UDP packet
// to the spec max, i.e. 65536. That being said, this value should likely
// be tuned lower to match your udp_payload size if using tools like
// telegraf.
//
// https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
//
// Reading packets from a UDP socket in golang actually only pulls
// one packet at a time, requiring a very fast reader to keep up with
// incoming data at scale. Reducing the overhead of the expected packet
// helps allocate memory faster (~10-25µs --> ~150ns with go1.5.2), thereby
// speeding up the processing of data coming in.
//
// NOTE: if you send a payload greater than the UDPPayloadSize, you will
// cause a buffer overflow...tune your application very carefully to match
// udp_payload for your metrics source
DefaultUDPPayloadSize = 65536
)
// Config holds various configuration settings for the UDP listener.
@ -44,6 +62,7 @@ type Config struct {
BatchPending int `toml:"batch-pending"`
ReadBuffer int `toml:"read-buffer"`
BatchTimeout toml.Duration `toml:"batch-timeout"`
UDPPayloadSize int `toml:"udp-payload-size"`
}
// WithDefaults takes the given config and returns a new config with any required
@ -65,5 +84,8 @@ func (c *Config) WithDefaults() *Config {
if d.ReadBuffer == 0 {
d.ReadBuffer = DefaultReadBuffer
}
if d.UDPPayloadSize == 0 {
d.UDPPayloadSize = DefaultUDPPayloadSize
}
return &d
}

View File

@ -19,6 +19,7 @@ retention-policy = "awesomerp"
batch-size = 100
batch-pending = 9
batch-timeout = "10ms"
udp-payload-size = 1500
`, &c); err != nil {
t.Fatal(err)
}
@ -38,5 +39,7 @@ batch-timeout = "10ms"
t.Fatalf("unexpected batch pending: %d", c.BatchPending)
} else if time.Duration(c.BatchTimeout) != (10 * time.Millisecond) {
t.Fatalf("unexpected batch timeout: %v", c.BatchTimeout)
} else if c.UDPPayloadSize != 1500 {
t.Fatalf("unexpected udp-payload-size: %d", c.UDPPayloadSize)
}
}

View File

@ -18,10 +18,6 @@ import (
)
const (
// UDPBufferSize is the maximum UDP packet size
// see https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
UDPBufferSize = 65536
// Arbitrary, testing indicated that this doesn't typically get over 10
parserChanLen = 1000
)
@ -163,7 +159,7 @@ func (s *Service) serve() {
return
default:
// Keep processing.
buf := make([]byte, UDPBufferSize)
buf := make([]byte, s.config.UDPPayloadSize)
n, _, err := s.conn.ReadFromUDP(buf)
if err != nil {
s.statMap.Add(statReadFail, 1)