23

In many google api's code samples i have seen this line of code.

time.sleep((2 ** n) + (random.randint(0, 1000) / 1000))

random.randint(0, 1000) / 1000 always return random milliseconds.

Whats is the use of this random milliseconds ?

Nijin Narayanan
  • 2,269
  • 1
  • 27
  • 46
  • 1
    In Python 2, (random.randint(0, 1000) / 1000)) will always return 0 (integer division returns an integer). Also, personally, I'd cap the exponential backoff, otherwise some of your clients may be waiting an undesirably long time. I'd use: min(64, (2 ** n)) + (random.randint(0, 1000) / 1000.0) – rouble Oct 29 '16 at 04:22

2 Answers2

27

Having a bit of randomness in situations like this is good. For example, if you have a large number of clients hitting the same server, having them use the same deterministic backoff could result in them hitting the server in perfect lockstep, which isn't desirable.

NPE
  • 464,258
  • 100
  • 912
  • 987
6

The reason is explained the API documentation:

In the above flow, random_number_milliseconds is a random number of milliseconds less than or equal to 1000. This is necessary to avoid certain lock errors in some concurrent implementations. The value of random_number_milliseconds must be redefined after each wait.

This is a common technique to "fuzz" the timing of APIs accesses to avoid thrashing caused by falling into recurring patterns of resource lock acquisition and release.

Raymond Hettinger
  • 199,887
  • 59
  • 344
  • 454