Crate r_fairdist

Source
Expand description

Fair Resource Distribution Algorithm

This project provides an implementation of the fairdist algorithm, a way to distribute a set of resources fairly amongst a dynamic number of users. Its infrastructure manages a hierarchy of users that currently hold shares of a resource. New users can be added at any time, and charges can be requested and released dynamically. The system ensures that every new user joining the system gets a guaranteed share of the total, regardless of how many users already hold resources.

The API abstracts over resources through the [counter::Counter] trait. This trait represents a set of numeric resource counters. In most cases these will just be usize integers. However, that is not a requirement. The resource counter is only required to “look like an integer” (see [counter::Counter] and its dependencies on the num crate). Furthermore, the API abstracts over users. It does not track users who interact with the system, but relies on the API user to provide a key or index that identifies the user of a given operation. This way the resource allocators can tell whether separate operations are performed by the same accounting user, or whether they are different. This is all information the system needs about the different users.

At the root level, the API user has to create a [Resource] object with the resource counters initialized to reflect the total resources available for distribution. These resources can now be requested through [Charge] objects. Charges are RAII-type objects that record a resource charge and make sure resources are released again when the Charge is dropped. To request resources, the API user must specify the accounting user to perform the charge as, as well as the amount to charge. If the quotas of the accounting user were exceeded, the charge is rejected. Otherwise, the charge will be granted. The allocators behind the resource objects make sure resources are distributed fairly. Additionally to the root-level [Resource] objects, the API allows to create sub-hierarchies to redistribute resources further. That is, new non-root-level [Resource] objects can be created given the accounting user to act as. This new sub-resource will then behave similar to the top-level resource and allow charges to be performed. It will ensure the same guarantees on its own sub-level, so the sub-distribution is again fair. Furthermore, the top-level guarantees are unaffected by sub-hierarchies that are formed. That is, individual accounting users cannot increase their resource shares by creating sub-hierarchies.

There are multiple possible algorithm that can be used for the individual allocations. In most cases the selected default is sufficient. However, the [allocator::Allocator] trait allows selecting from a range of predefined allocators, as well as creating individual allocators. The default allocator guarantees quasilinear shares to every user of the system. In particular, this means regardless how many users join the allocation system, each one is guaranteed a share of 1 over O(n * log(n)^2) of the total.

Modules§

  • Allocation Calculations
  • Abstract representation of a multi-dimensional resource counter.

Structs§

  • A charge represents temporarily borrowed resources.
  • A resource that can be distributed amongst users.
  • A subscription to a resource.