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
  • 2
  • 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

29

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
  • 486,780
  • 108
  • 951
  • 1,012
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
  • 216,523
  • 63
  • 388
  • 485