Skip to main content

SwapFullContainers

Move Type: Swap Complexity: O(containers) with full container exchange

Exchange ALL objects between two containers in one move. Much simpler than pairwise swaps - useful for container rebalancing and migration scenarios.

Overview

SwapFullContainers evaluates exchanging all objects between the hot container and every other container. Unlike regular Swap which tries individual object pairs, this move type swaps entire container contents at once.

Use when:

  • Containers have similar sizes
  • Want to relocate entire workload (e.g., migrate server)
  • Capacity constraints block individual moves
  • Container-level rebalancing more important than object-level

Avoid when:

  • Containers have very different sizes
  • Need fine-grained object placement
  • Most objects in containers are well-placed
  • Container capacities would be violated

Quick Example

# Exchange entire container contents
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SwapFullContainersMoveTypeSpec(), # Full container swaps
]
)
)
)

Parameters

ParameterTypeRequiredDefaultDescription
(none)---SwapFullContainers has no configuration parameters

How It Works

Given a hot container (the container contributing most to the objective):

  1. Select cold container: Pick a different container
  2. Evaluate full swap: Test exchanging ALL objects between hot and cold containers
  3. Repeat: Try all other containers as potential swap partners
  4. Apply best: Apply the full container swap that improves objective most

Visual Example

Before swap:                      After full container swap:
┌─────────────────┐ ┌─────────────────┐
│ Hot Container │ │ Hot Container │
│ • obj1 │ │ • objA ←───────┼─┐
│ • obj2 │ <========> │ • objB │ │
│ • obj3 │ │ • objC │ │
└─────────────────┘ └─────────────────┘ │

┌─────────────────┐ ┌─────────────────┐ │
│ Cold Container │ │ Cold Container │ │
│ • objA ───────┼──┐ │ • obj1 │ │
│ • objB │ │ │ • obj2 │ │
│ • objC │ │ │ • obj3 ←───────┼─┘
└─────────────────┘ │ └─────────────────┘

All objects exchanged in ONE move

Comparison with Regular Swap

AspectSwapSwapFullContainers
GranularityIndividual object pairsEntire containers
ComplexityO(N² × C)O(C)
Moves per iterationThousands-millionsTens-hundreds
Use caseFine-grained optimizationContainer-level rebalancing

Complexity

Moves evaluated per iteration: O(C)

Where:

  • C = number of containers

Example:

  • System: 100 containers
  • Regular Swap with 1000 objects each: 1000² × 100 = 100 million pairwise swaps
  • SwapFullContainers: 100 full container swaps

Note: While fewer moves are evaluated, each full container swap is more expensive to evaluate since all objects in both containers must be considered.

Usage Patterns

Server Migration

Move entire server workload:

# Migrate all shards from overloaded server to another
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SwapFullContainersMoveTypeSpec(), # Swap all shards between servers
]
)
)
)

Container Consolidation

Rebalance container-level load:

# Container-level rebalancing for similar-sized containers
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SwapFullContainersMoveTypeSpec(), # Swap entire containers
]
)
)
)

Combined with Object-Level Moves

Use for coarse adjustment, then fine-tune:

# Multi-stage: coarse container rebalancing, then fine object placement
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SwapFullContainersMoveTypeSpec(), # Container-level rebalancing
SwapMoveTypeSpec(), # Fine-tune with object swaps
SingleMoveTypeSpec(), # Final object placement
]
)
)
)

Capacity-Constrained Full Swaps

When individual moves blocked by capacity:

# Full swaps can work when individual moves are capacity-blocked
# Note: Full swaps may violate capacity if container sizes differ
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SwapFullContainersMoveTypeSpec(), # Try full container exchanges
SwapMoveTypeSpec(), # Fall back to capacity-neutral object swaps
]
)
)
)

Performance Characteristics

Scalability

ContainersObjects per ContainerFull Swaps EvaluatedEvaluation Time
101K10<1s
1001K1001-5s
10001K100010-60s
10K1K10K2-10 min

Note: Evaluation time depends heavily on objective function complexity.

When Does It Help?

SwapFullContainers helps when:

  • Similar container sizes: Swapping makes sense
  • Container-level imbalance: Distribution across containers is wrong
  • Capacity-blocked: Individual moves violate capacity
  • Migration scenarios: Moving entire workloads
  • Coarse rebalancing: Need big changes quickly

SwapFullContainers does NOT help when:

  • Variable container sizes: Swapping creates more imbalance
  • Object-level issues: Problem is specific object placement
  • Most objects well-placed: Full swap undoes good placements
  • Capacity highly varied: Full swaps likely to violate constraints

Comparison with Variants

Move TypeGranularityComplexityCapacity HandlingUse Case
SwapObject pairsO(N²)Capacity-neutralGeneral swapping
SwapSampledSampled pairsO(S²)Capacity-neutralLarge-scale swapping
SwapFullContainersFull containersO(C)May violateContainer migration
SwapFullWithEmptyFull to emptyO(C_empty)Consolidation-friendlyEmptying containers

Decision tree:

  1. Need to empty containers?SwapFullWithEmpty
  2. Container-level rebalancing?SwapFullContainers
  3. Object-level optimization?Swap or SwapSampled
  4. Capacity-constrained?Swap (capacity-neutral by definition)

Troubleshooting

Problem: SwapFullContainers not finding good moves

Diagnosis: Container sizes too different or no beneficial full swaps exist

Solutions:

  • Check container size distribution
  • Use Swap for fine-grained object swaps instead
  • Combine with Single to move objects first
  • May already be at good container-level balance

Problem: Capacity violations after full swap

Diagnosis: Full container swap violated capacity constraints

Solutions:

  • This is expected - SwapFullContainers doesn't guarantee capacity respect
  • Set tight capacity constraints to prevent violations
  • Use Swap instead (capacity-neutral)
  • Follow up with Single to fix violations

Problem: Undoing good object placements

Diagnosis: Full swap moves well-placed objects

Solutions:

  • Use SwapFullContainers only for initial coarse rebalancing
  • Follow with object-level moves (Single, Swap)
  • Consider if full container swap is appropriate for this problem
  • Use avoidMoving constraints for critical objects

Problem: Too few improving moves found

Diagnosis: Only C moves evaluated, may miss opportunities

Solutions:

  • This is expected - trade-off for simplicity
  • Combine with Swap or SwapSampled
  • Use multi-stage: full swap first, then object swaps
  • Consider if problem needs container-level or object-level rebalancing

When to Use SwapFullContainers

DO use when:

  • Migrating entire server/container workloads
  • Container-level rebalancing (similar-sized containers)
  • Coarse initial rebalancing before fine-tuning
  • Capacity constraints block most individual moves
  • Testing "what if we swapped these two servers"

DO NOT use when:

  • Containers have very different sizes
  • Need fine-grained object placement
  • Capacity constraints must be strictly respected
  • Most objects are already well-placed

Swap variants:

Complementary:

  • Single - Use before/after for object-level tuning
  • SingleEndChain - Alternative for capacity issues

Use together:

  1. SwapFullContainers for coarse container rebalancing
  2. Swap or Single for fine object placement
  3. Achieves both container and object level optimization

Source Code

Next Steps