damus icon indicating copy to clipboard operation
damus copied to clipboard

apply exponential backoff to retrying stale relay connections

Open bryanmontz opened this issue 2 years ago • 4 comments

The energy impact report in Xcode shows High or Very High energy usage which is likely related to the heavy network usage of Damus. One way to reduce energy impact slightly is to stop endlessly retrying relay connections that don't seem to be working.

This PR applies an exponential backoff algorithm so that we are still retrying connections, but we don't just do that every 5 seconds. Instead we keep track of how many times we've retried per relay and use that to calculate a delay. I've set the base delay to 2 seconds, which will be raised to the power of the number of previous retry attempts. So if a relay isn't responding, it will be retried after: 1 second, then 2 seconds, then 4 seconds, then 8 seconds, and so on.

The previous retry attempts will be reset for every app session, but we could also reset it on app resume.

Before: damus_—_RelayPool_swift In this screenshot ^, each retry is 5 seconds apart and it continues endlessly.

After: damus_—_damus_xcodeproj

I'd recommend a further step of limited each relay to a maximum of retries, such as 5, and then disconnecting and not retrying that relay anymore, but I wanted to get your feedback first.

bryanmontz avatar Feb 23 '23 12:02 bryanmontz

If those delays are too short at the beginning, the exponential backoff algorithm's constants can be tweaked and tuned to your liking.

One example might be that the first delay is 5 seconds, then 25 seconds, then 125, etc.

bryanmontz avatar Feb 23 '23 13:02 bryanmontz

oh good call. I still need to revisit the connection logic in general. its a huge hack

jb55 avatar Feb 24 '23 20:02 jb55

Since you said it needed work, I took the liberty and added some refinements to RelayConnection and RelayPool. Some highlights:

  1. All event decoding is done off the main thread.
  2. Adds a maximum number of retry attempts per relay, after which we mark it as broken and stop trying to connect to it.
  3. Adds a State enum for RelayConnection, rather than separate bool properties.

bryanmontz avatar Feb 25 '23 04:02 bryanmontz

Next I plan to add some tests for reassurance.

bryanmontz avatar Feb 25 '23 04:02 bryanmontz

will test this soon

jb55 avatar Mar 15 '23 16:03 jb55

this seems much better

jb55 avatar Mar 15 '23 16:03 jb55

Awesome. I'd be happy to continue working on this too. I'd love for Damus to be the best nostr client for relay connections.

bryanmontz avatar Mar 15 '23 16:03 bryanmontz

This is causing an issue where damus fails to reconnect and you have to restart the app. I suspected this might crop up in an exp backoff scheme + flaky connections. I may have to revert this for now.

jb55 avatar Mar 17 '23 13:03 jb55

reverted in 9091cb1aae43633673794009bdc576faddc6ed35

jb55 avatar Mar 17 '23 13:03 jb55

Sorry about that. Yeah you can't just permanently stop connecting to a relay. I'll spend some more time with it and make sure it'll reset on app resume so that it won't permanently stop connecting.

bryanmontz avatar Mar 17 '23 13:03 bryanmontz