timehop / apns

A Go package to interface with the Apple Push Notification Service
https://godoc.org/github.com/timehop/apns
MIT License
185 stars 47 forks source link

Using Nagle's algorithm? #32

Closed willfaught closed 1 year ago

willfaught commented 9 years ago

https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html states in part:

The binary interface employs a plain TCP socket for binary content that is streaming in nature. For optimum performance, batch multiple notifications in a single transmission over the interface, either explicitly or using a TCP/IP Nagle algorithm.

Was net.TCPConn.SetNoDelay= false considered? The quotation seems to indicate doing this would yield better performance.

taylortrimble commented 9 years ago

This is a great consideration. Batching is always tricky, since different use cases demand different approaches.

Low throughput, latency sensitive

Negatively impacted by Nagle's via SetNoDelay, since the implementation is basically a timeout (around 500ms or so?)

High throughput, high cohesion

High cohesion means you know you're going to send a lot of pushes; for example, you're Netflix telling everyone who signed up for House of Cards updates that Series 3 became available :us: or Uber's letting everyone splitting the fare in your ride know how much they're paying.

If the high throughput, high cohesion pushes are also latency sensitive, it makes sense to use something like a bufio.Writer that you can flush when your group of pushes is serialized.

In the non-latency-sensitive case, a properly sized buffered writer will also have less overhead than Nagle's.

High throughput, low cohesion

Low cohesion means the service can't tell when it's going to send a ton of pushes, like sending pushes in response to 1,000 simultaneous but unrelated requests. Since the service can't flush a buffer intelligently, it must deal with either constant network overhead (Nagle's off) or latency in low throughput periods (Nagle's on).

Most applications will find Nagle's a good choice here.

Conclusion?

I'd advocate for the default connection to be Nagle's-off. Once you get to the high-throughput case, you need to determine if you can intelligently flush a buffer of data (cohesion), if latency is important, etc. There's no one size fits all, so just letting the user of the lib swap out our default connection for a more fancy :cocktail: connection that suits their needs is probably the way to go. I wouldn't provide anything fancy to start.

nathany commented 9 years ago

go-libapns takes the approach of batching multiple notifications to fill the tcp frame https://github.com/joekarl/go-libapns