diff options
author | Dries Buytaert <dries@buytaert.net> | 2011-05-13 22:34:19 -0400 |
---|---|---|
committer | Dries Buytaert <dries@buytaert.net> | 2011-05-13 22:34:19 -0400 |
commit | 7d1ae1167ddf733278841824aa0df7dab2f34661 (patch) | |
tree | d7cd5db47e8d61eb07e4fe5f18dbf55b2f3c3484 /includes/lock.inc | |
parent | 33e746fc34ff2af303aca27b11c65a638bbc11a9 (diff) | |
download | brdo-7d1ae1167ddf733278841824aa0df7dab2f34661.tar.gz brdo-7d1ae1167ddf733278841824aa0df7dab2f34661.tar.bz2 |
- Patch #802856 by catch, pillarsdotnet: make lock_wait() wait less.
Diffstat (limited to 'includes/lock.inc')
-rw-r--r-- | includes/lock.inc | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/includes/lock.inc b/includes/lock.inc index 2eb7b9a90..42f1906f2 100644 --- a/includes/lock.inc +++ b/includes/lock.inc @@ -187,7 +187,7 @@ function lock_may_be_available($name) { * lock. This will block further execution until the lock is available or the * specified delay in seconds is reached. This should not be used with locks * that are acquired very frequently, since the lock is likely to be acquired - * again by a different request during the sleep(). + * again by a different request while waiting. * * @param $name * The name of the lock. @@ -198,12 +198,32 @@ function lock_may_be_available($name) { * TRUE if the lock holds, FALSE if it is available. */ function lock_wait($name, $delay = 30) { - $delay = (int) $delay; - while ($delay--) { + // Pause the process for short periods between calling + // lock_may_be_available(). This prevents hitting the database with constant + // database queries while waiting, which could lead to performance issues. + // However, if the wait period is too long, there is the potential for a + // large number of processes to be blocked waiting for a lock, especially + // if the item being rebuilt is commonly requested. To address both of these + // concerns, begin waiting for 25ms, then add 25ms to the wait period each + // time until it reaches 500ms. After this point polling will continue every + // 500ms until $delay is reached. + + // $delay is passed in seconds, but we will be using usleep(), which takes + // microseconds as a parameter. Multiply it by 1 million so that all + // further numbers are equivalent. + $delay = (int) $delay * 1000000; + + // Begin sleeping at 25ms. + $sleep = 25000; + while ($delay > 0) { // This function should only be called by a request that failed to get a // lock, so we sleep first to give the parallel request a chance to finish // and release the lock. - sleep(1); + usleep($sleep); + // After each sleep, increase the value of $sleep until it reaches + // 500ms, to reduce the potential for a lock stampede. + $delay = $delay - $sleep; + $sleep = min(500000, $sleep + 25000, $delay); if (lock_may_be_available($name)) { // No longer need to wait. return FALSE; |