1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 16:52:41 +01:00

Reduce collision rate for concurrency-limiting slot locks

Summary:
Depends on D19077. Ref T13073. When we're using slot locks to enforce a limit (e.g., maximum of 5 simultaneous things) we currently load locks owned by the blueprint to identify which slots are likely to be free.

However, this isn't right: the blueprint doesn't own these locks. The resources do.

We still get the right behavior eventually, but we incorrectly identify that every slot lock is always free, so as the slots fill up we'll tend to guess wrong more and more often.

Instead, load the slot locks by name explicitly.

Test Plan: Implemented lock-based limiting on `HoaxBlueprint`, `var_dump()`'d the candidate locks, saw correct test state for locks. Acquired leases without releasing, got all of the slots filled without any slot lock collisions (previously, the last slot or two tended to collide a lot).

Subscribers: yelirekim, PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13073

Differential Revision: https://secure.phabricator.com/D19078
This commit is contained in:
epriestley 2018-02-13 09:49:11 -08:00
parent 2994753d23
commit 619943bea0

View file

@ -396,16 +396,20 @@ abstract class DrydockBlueprintImplementation extends Phobject {
}
// For reasonable limits, actually check for an available slot.
$locks = DrydockSlotLock::loadLocks($blueprint_phid);
$locks = mpull($locks, null, 'getLockKey');
$slots = range(0, $limit - 1);
shuffle($slots);
$lock_names = array();
foreach ($slots as $slot) {
$slot_lock = "allocator({$blueprint_phid}).limit({$slot})";
if (empty($locks[$slot_lock])) {
return $slot_lock;
$lock_names[] = "allocator({$blueprint_phid}).limit({$slot})";
}
$locks = DrydockSlotLock::loadHeldLocks($lock_names);
$locks = mpull($locks, null, 'getLockKey');
foreach ($lock_names as $lock_name) {
if (empty($locks[$lock_name])) {
return $lock_name;
}
}
@ -414,7 +418,8 @@ abstract class DrydockBlueprintImplementation extends Phobject {
// lock will be free by the time we try to take it, but usually we'll just
// fail to grab the lock, throw an appropriate lock exception, and get back
// on the right path to retry later.
return $slot_lock;
return $lock_name;
}