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
net: default TCP Keep-Alive interval causes significant power usage #48622
Comments
As a workaround, it should be possible to call syscall.Setsockoptint on the FD of the socket. Example here for different socket options: https://stackoverflow.com/questions/40544096/how-to-set-socket-option-ip-tos-for-http-client-in-go-language#40549614 |
CC @neild |
Hello, any updates, discussions, ideas? |
The argument for why there is a default keep-alive value is #23459. It is of course possible for a program to change the default, as I think you know. Are you suggesting that we change the default behavior on android and ios? If so, what should we change it to? |
The original idea was to have about 3 minutes for dead peer detection, but the current implementation does that suboptimal. RIght now it is achieved by sending 10 keep-alive packets every 15 seconds (on Linux), after which, if the peer did not respond to any of them, the connection is considered broken after 2 minutes 30 seconds (15 + 15*9).
However, the same could be achieved without spending too much battery life, by configuring bigger initial timeout and smaller number of packets TCP_KEEPCNT. Like this:
This configuration begins probing the client only after 3 minutes (180 seconds) of inactivity on the socket. After 2 keep-alive packets with 15 seconds interval, or 3 minutes 30 seconds, the connection would be considered broken.
This should be changed globally, because changing it only on Android/iOS would still affect the devices connecting to the servers with low timeouts. Please also take a look at the arguments here: #23459 (comment) I also believe that 3 minute timeout is still low, consider setting it to at least 5 minutes. |
Note that I think there are some portability concerns here. For example, as far as I know OpenBSD does not permit setting these values individually for each socket. |
Regarding "why 5 minutes":
|
Nothing happened for 1.19. Moving to 1.20. |
Personally i think the main problem here is not the count but the problem that we are not able to maintain keep alive interval and idle timeout seperatly. We also have a similar problem with tcp keep alive mechanism in golang. It is practically useless for us because of this issue since 2014 have a look here please too: #8328 Also my comment here: Being able to have a high idle time would prevent flodding the network draining bateries and having at the same time a low interval would help to dectect failed connections fast. That would be enough for us. Ofcourse haveing also possibility to control keep alive count would be good too but maybe this would not even necessary because you could adjust the interval according to your needs. |
Description
Golang's default TCP Keep-Alive is 15 seconds for both listening and connecting sockets.
Every time you use golang software, or connect to the website with long-polling/websockets running golang, your cell phone battery drains a lot quicker than it should.
The change has been originally introduced by:
https://go-review.googlesource.com/c/go/+/107196
There's a modern proxy application called V2ray, and it's available on Android as well. It's written in Go.
I noticed that my phone sends keep-alive packets every 3-5 seconds while keeping only 7 TCP sockets opened. The battery died rather quickly.
Current Golang version has two issues with TCP Keep-Alive interval:
KeepAlive
option changes both Keep-Alive time (TCP_KEEPIDLE) and Keep-Alive interval (TCP_KEEPINTVL) to the same value (can't be configured separately).The latest item behavior is totally incorrect in my opinion. Linux uses 9 keep-alive probes of TCP_KEEPINTVL interval before closing the socket, so setting
dial.Dialer KeepAlive
to 300 seconds gives 50 minutes of actual socket hang detection.If golang could set only
TCP_KEEPIDLE
and not touchTCP_KEEPINTVL
, 300 second KeepAlive with the default Linux behavior (TCP_KEEPINTVL=75) would close the socket after ≈16 minutes, which is correct and expected. The latest behavior is widely used elsewhere.Please note that golang also sets
TCP_KEEPIDLE
andTCP_KEEPINTVL
by default for all listening and accepted sockets: not only golang clients, but also any clients connecting to golang servers are affected by short timeout.What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?Reproducible on any architecture and any OS.
What did you do?
Use
dial.Dialer / net.Listener
with default settings.What did you expect to see?
Sane Keep-Alive values
What did you see instead?
Very short Keep-Alive period and inability to tune TCP_KEEPIDLE and TCP_KEEPINTVL separately.
The text was updated successfully, but these errors were encountered: