Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

moving UDP payload size to config option, improve throughput performance #5201

Merged
merged 3 commits into from
Dec 22, 2015
Merged

Conversation

sebito91
Copy link
Contributor

Current UDP service alloc's a byte slice at max theoretical UDP packet size for each iteration of reading from the socket. This is inefficient in terms of memory allocation (ReadFromUDP pulls one packet at a time, so it's largely overkill for 95% of use cases) and execution time (inordinate about of time spent in alloc, causes backpressure on UDP socket at scale + extra overhead for GC).

Proposed changes add UDP payload size as a config option (default is UDP max) and help speed up throughput when closely aligned with payload size sent from metrics source (e.g. udp_payload in telegraf).

To test/prove this, you can use this tester script (thanks @daviesalex) with different slice sizes. Testing with max UDP at 65536, alloc times hover around 10-20us but drop to ~120-130ns when size dropped to match typical udp_payload at 1500.

package main

import (
        "fmt"
        "time"

func main() {
        for { 
                start := time.Now()

                foo := make([]byte, 1500)

                now := time.Now()
                diff := now.Sub(start)
                fmt.Printf("ndiff: %v (%d)\n", diff, len(foo))
        } 
}

moving UDP payload size to optional config choice to imporove throughput performance
@otoolep
Copy link
Contributor

otoolep commented Dec 22, 2015

Thanks guys.

@sebito91 -- have you signed the CLA?

//
// https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
//
// Reading packets from a UDP socket in golang actually only pulls
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: golang -> Go. We never call it golang. :-)

@sebito91
Copy link
Contributor Author

Heh, I'll remove 'golang'...and yes already signed the CLA.

@otoolep
Copy link
Contributor

otoolep commented Dec 22, 2015

This makes a lot of sense to me -- thanks @sebito91 and @daviesalex

+1 on green.

@jwilder @sparrc -- can I get a second review?

@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, our convention is that we set the value of commented out flags to the default. However, a note here explaining that a lower value would be better for most would make sense.

Sound good?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, will update now.

@jwilder
Copy link
Contributor

jwilder commented Dec 22, 2015

👍

@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rename this constant to MaxUDPBufferSize and modify the service's Open function to return an error when the payload size is set too high in the config?

It would be nice to either error or give some kind of warning to the user if they set the buffer size unnecessarily high.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff actually removes that const in lieu of a config var. See original commit:

sebito91@3bf5d9c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I know. I thought it might be valuable to keep this constant and use it to ensure that the payload size doesn't get set unnecessarily high by a user.

It's a usability concern, not one of correctness.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's nothing wrong with allocating a buffer size > 65536, the only reason that value was selected was to provide guidance on an upper bound. Nothing stopping you from setting that higher if you really want (in terms of usability).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind then.

otoolep added a commit that referenced this pull request Dec 22, 2015
moving UDP payload size to config option, improve throughput performance
@otoolep otoolep merged commit a63d262 into influxdata:master Dec 22, 2015
@sparrc
Copy link
Contributor

sparrc commented Dec 23, 2015

Thanks much @sebito91

@daviesalex daviesalex mentioned this pull request Dec 23, 2015
@jwilder jwilder added this to the 0.10.0 milestone Feb 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants