wrench::GreedyServerlessScheduler

class GreedyServerlessScheduler : public wrench::ServerlessScheduler

Policy-configurable serverless scheduler with greedy placement, resource reclamation, and image-preparation planning.

This scheduler combines policies for invocation failure, node activation/deactivation, invocation ordering, node eligibility, reusable-container selection, eviction, plan selection, and prewarming. Default implementations are installed by the constructor and can be replaced with setPolicy().

Policies operate within a fixed orchestration and placement algorithm. Invocations are considered sequentially; each selected plan changes the working resources available to later invocations. Earlier choices are not revisited to optimize the complete batch. Policy replacement therefore does not change the precedence of the scheduling phases or placement passes.

  1. Records the failure policy’s decisions and removes those invocations from the local worklist.

  2. Obtains the node-scaling policy’s activation and deactivation requests. Nodes selected for deactivation are excluded from subsequent planning in this round. Requested activations do not become usable until the compute service processes their completion.

  3. Orders the surviving worklist in place using the ordering policy.

  4. Considers each invocation, selects a dispatch or image-preparation plan when possible, and applies the selected plan’s accounting changes to the working state. An invocation for which no plan is selected remains pending; it does not prevent consideration of later invocations.

  5. Evaluates prewarming against the post-placement working state and appends the resulting container-creation requests.

  6. Collects the installed policies’ requested wakeup dates.

Scheduling round

Each schedule() call constructs a fresh ServerlessSchedulingState and:

Failure selection, worker activation, ordering, prewarming, and wakeup collection are outside the per-invocation placement loop. They are evaluated even when the worklist is empty. Node selection, reusable-container selection, eviction, and plan selection are evaluated as placement needs them. Invocation ordering is not strict head-of-line blocking.

  1. Ask the reusable-container policy for an initialized, compatible container with remaining invocation capacity. The container need not be idle: an occupied container may accept more work up to its limit.

  2. Construct cold-dispatch alternatives on nodes where every required image layer is resident on disk and in RAM. Reclamation may be needed for private RAM, private disk space, or a container position.

  3. Select the first node where some required RAM residency is still missing, but every missing layer is already being loaded.

  4. Construct alternatives that initiate the remaining RAM loads on nodes where every required layer is already on disk.

  5. Select the first node where some required disk residency is still missing, but every missing layer is already being copied.

  6. Construct alternatives that initiate the remaining disk copies.

Placement precedence

For an invocation, the node-selection policy supplies an eligibility set, not a ranking. The scheduler retains selected, already-activated nodes with remaining node-wide invocation capacity, preserving their traversal order. It then tries these passes in order:

The first pass that selects a node determines the outcome for this invocation. The plan-selection policy compares alternatives within the cold-dispatch, RAM-load, and disk-copy passes; it does not compare plans across readiness levels or override the reusable-container decision.

The working state distinguishes three count constraints: remaining invocations per node, remaining container positions per node, and remaining invocations per existing initialized container. These counts are separate from RAM/disk availability and physical CPU capacity.

Working state and capacity accounting

The worklist is a copy of invocation references, not Invocation objects. Filtering and ordering it do not change the service’s pending collection. Runtime containers and invocations remain shared objects; planning must not mutate them to simulate application of a returned decision.

A selected dispatch consumes one unit of node invocation capacity. Reuse also consumes one unit of the existing container’s invocation capacity. Cold dispatch instead consumes a container position and its private RAM and disk allocations. A selected idle-container termination returns its private resources and container position and removes the container from the working collection. Selected transfers reserve their destination space and mark their layers as in progress, not resident.

Alternative plans are evaluated before committing their changes to the working state. Only the chosen alternative’s changes constrain subsequent placement. This bookkeeping is local to the round: it is not a persistent service-side reservation or invocation-to-node binding.

In particular, selecting a node to wait for image preparation does not consume invocation capacity or reserve a future container position. It protects the invocation’s required layers on that node for the remainder of this round but emits no operation. Starting a transfer likewise does not reserve all resources needed for a later container. Future rounds reassess feasibility from the observed system state.

Layers needed by the invocation, earlier chosen plans, ongoing transfers, or containers retained by the tentative plan are excluded as appropriate. Evicting a disk layer also requires removal of its RAM copy when present. Reclamation is feasible only if it satisfies the required byte deficits and frees enough container positions.

Reclamation

Reclamation considers idle containers first, then RAM layers, then disk layers. The eviction policy selects victims from eligible candidates. Required resources are compared with currently available resources to obtain deficits; needing one new container does not necessarily require terminating an existing container. Only container termination can free a container position; layer eviction addresses byte deficits.

The scheduler appends the proposals and accounts for their container positions; it does not perform another RAM/disk planning pass over them. Each proposal creates one environment, so repeated function/node pairs request distinct containers. Prewarming has no assigned client invocation and does not consume invocation-concurrency capacity, but retains its container resources. Its lower precedence applies to this scheduling round, not to requests that arrive after prewarming has started.

Prewarming

Prewarming is considered after current requests and their image-preparation plans. The policy must select a jointly feasible batch using the remaining container positions, RAM, and disk, with required layers already resident on activated workers. This phase does not plan additional evictions or transfers to make its proposals feasible.

The result describes operations for ServerlessComputeService to apply. schedule() neither executes them nor waits for completion. The service applies decision categories in its own order and performs its runtime checks. The batch is not an atomic transaction. Dependencies on operation completion are handled through later scheduling rounds, not by assuming that a requested copy, load, initialization, or activation is complete.

Wakeups and execution

After policy evaluation, the scheduler takes the minimum reported wakeup date. DBL_MAX means no request; if all policies return it, the output’s optional wakeup date remains unset. Other dates must be finite absolute simulated dates strictly later than the current time. Deadlines are validated (i.e., an exception is thrown if stale), when taking the minimum.

Note

The working state is not a complete projected runtime state. The invocation worklist still contains requests selected for dispatch, and newly planned containers do not yet exist as selectable Container objects. Policies must not infer the undispatched backlog from worklist size alone or treat the container collections as a complete post-batch inventory.

Public Functions

GreedyServerlessScheduler()

Constructor. Creates a greedy scheduling with the following default policies (use setPolicy() to change them):

  • Invocation ordering policy: FCFSServerlessInvocationOrderingPolicy

  • Node selection policy: SelectAllPossibleServerlessNodeSelectionPolicy

  • Eviction policy: FewestServerlessEvictionPolicy

  • Plan selection policy: EvictionAverseServerlessPlanSelectionPolicy

  • Node scaling policy: ActivateOneWhenNoFreeSlotServerlessNodeActivationPolicy

  • Container prewarm policy: NeverPrewarmServerlessContainerPrewarmPolicy

  • Invocation failing policy: NeverFailServerlessInvocationFailingPolicy

ServerlessContainerPrewarmPolicy *getContainerPrewarmPolicy() const

Get the scheduler’s container prewarm policy.

Returns:

the policy

ServerlessEvictionPolicy *getEvictionPolicy() const

Get the scheduler’s eviction policy.

Returns:

the policy

ServerlessInvocationFailingPolicy *getInvocationFailingPolicy() const

Get the scheduler’s invocation failing policy.

Returns:

the policy

ServerlessInvocationOrderingPolicy *getInvocationOrderingPolicy() const

Get the scheduler’s invocation ordering policy.

Returns:

the policy

ServerlessNodeScalingPolicy *getNodeScalingPolicy() const

Get the scheduler’s node activation policy.

Returns:

the policy

ServerlessNodeSelectionPolicy *getNodeSelectionPolicy() const

Get the schedule’s node selection policy.

Returns:

the policy

ServerlessPlanSelectionPolicy *getPlanSelectionPolicy() const

Get the scheduler’s plan selection policy.

Returns:

the policy

ServerlessReusableContainerSelectionPolicy *getReusableContainerSelectionPolicy() const

Get the scheduler’s idle container selection policy.

Returns:

the policy

virtual std::shared_ptr<ServerlessSchedulingDecisions> schedule(const ServerlessStateOfTheSystem *state) override

Build one batch of scheduling decisions using a mutable planning snapshot without modifying the supplied invocation vector.

Records selected invocation failures, filters and orders the local worklist, requests worker activation, and greedily considers the remaining requests. For each selected dispatch or preparation plan, updates the working resource counts, residency information, and protected layers. Finally evaluates prewarming against that working state and combines the installed policies’ requested wakeup dates.

A pending invocation need not receive an operation in this round. In particular, choosing to wait for an existing transfer protects its layers but does not reserve invocation capacity or bind it to that node. Copies and loads do not become completed residency changes during planning.

The returned operations are intentions for the service to apply, not executed actions or an atomic reservation. See the class documentation for phase precedence, reusable-container capacity, and planning semantics.

Parameters:

state – Current system state from which the planning snapshot is built.

Returns:

A new ServerlessSchedulingDecisions object. Its operation lists may all be empty, independently of whether a future wakeup is requested.

void setPolicy(std::shared_ptr<ServerlessContainerPrewarmPolicy> policy)

Policy setter.

Parameters:

policy – A container prewarm policy (at your own risk once the simulation has started)

void setPolicy(std::shared_ptr<ServerlessEvictionPolicy> policy)

Policy setter.

Parameters:

policy – A serverless eviction policy (at your own risk once the simulation has started)

void setPolicy(std::shared_ptr<ServerlessInvocationFailingPolicy> policy)

Policy setter.

Parameters:

policy – An invocation failing policy (at your own risk once the simulation has started)

void setPolicy(std::shared_ptr<ServerlessInvocationOrderingPolicy> policy)

Policy setter.

Parameters:

policy – An invocation ordering policy (at your own risk once the simulation has started)

void setPolicy(std::shared_ptr<ServerlessNodeScalingPolicy> policy)

Policy setter.

Parameters:

policy – A node activation policy (at your own risk once the simulation has started)

void setPolicy(std::shared_ptr<ServerlessNodeSelectionPolicy> policy)

Policy setter.

Parameters:

policy – A node selection policy (at your own risk once the simulation has started)

void setPolicy(std::shared_ptr<ServerlessPlanSelectionPolicy> policy)

Policy setter.

Parameters:

policy – A plan selection policy (at your own risk once the simulation has started)

void setPolicy(std::shared_ptr<ServerlessReusableContainerSelectionPolicy> policy)

Policy setter.

Parameters:

policy – A reusable container selection policy (at your own risk once the simulation has started)