Class SamplingAllocationStrategy

java.lang.Object
reactor.pool.introspection.SamplingAllocationStrategy
All Implemented Interfaces:
AllocationStrategy

public final class SamplingAllocationStrategy extends Object implements AllocationStrategy
An AllocationStrategy that delegates to an underlying AllocationStrategy and samples the getPermits(int) and returnPermits(int) methods.

Only a given percentage of calls are sampled, and these are stored as stacktraces in the sampling strategy. If a AllocationStrategy.returnPermits(int) call fails, a new IllegalArgumentException is thrown with a composite cause that represents all the sampled calls (see Exceptions.unwrapMultiple(Throwable)).

The two types of calls are sampled separately. The reservoir sampling algorithm is used to instantiate a sampling decision bitset over 100 slots, which are then applied to windows of 100 calls. Access to the delegate field is possible, as well as gettingSamplingRate/returningSamplingRate configuration fields and gettingSamples/returningSamples collections.

Author:
Simon Baslé
  • Field Details

    • delegate

      public final AllocationStrategy delegate
      The delegate AllocationStrategy backing this sampling strategy.
    • gettingSamples

      public final LinkedList<Throwable> gettingSamples
      The list of samples for getPermits(int) calls, as Throwable that trace back to the callers of the sampled calls.
    • gettingSamplingRate

      public final double gettingSamplingRate
      The configured sampling rate for getPermits(int) calls, as a double between 0d and 1d (percentage).
    • returningSamples

      public final LinkedList<Throwable> returningSamples
      The list of samples for returnPermits(int) calls, as Throwable that trace back to the callers of the sampled calls.
    • returningSamplingRate

      public final double returningSamplingRate
      The configured sampling rate for returnPermits(int) calls, as a double between 0d and 1d (percentage).
  • Method Details

    • sizeBetweenWithSampling

      public static SamplingAllocationStrategy sizeBetweenWithSampling(int min, int max, double getPermitsSamplingRate, double returnPermitsSamplingRate)
      Parameters:
      min - the minimum number of permits (see PoolBuilder.sizeBetween(int, int))
      max - the maximum number of permits (see PoolBuilder.sizeBetween(int, int))
      getPermitsSamplingRate - the sampling rate for AllocationStrategy.getPermits(int) calls (0.0d to 1.0d)
      returnPermitsSamplingRate - the sampling rate for AllocationStrategy.returnPermits(int) calls (0.0d to 1.0d)
      Returns:
      a sampled AllocationStrategy that otherwise behaves like the PoolBuilder.sizeBetween(int, int) strategy
    • withSampling

      public static SamplingAllocationStrategy withSampling(AllocationStrategy delegate, double getPermitsSamplingRate, double returnPermitsSamplingRate)
      An AllocationStrategy that wraps a delegate and samples calls to AllocationStrategy.getPermits(int) and AllocationStrategy.returnPermits(int). Only a given percentage of calls are sampled, and these are stored as stacktraces in the sampling strategy. If a AllocationStrategy.returnPermits(int) call fails, a new IllegalArgumentException is thrown with a composite cause that represents all the sampled calls (see Exceptions.unwrapMultiple(Throwable)).

      The two types of calls are sampled separately. The reservoir sampling algorithm is used to instantiate a sampling decision bitset over 100 slots, which are then applied live to windows of 100 calls.

      Parameters:
      delegate - the underlying AllocationStrategy
      getPermitsSamplingRate - the sampling rate for AllocationStrategy.getPermits(int) calls (0.0d to 1.0d)
      returnPermitsSamplingRate - the sampling rate for AllocationStrategy.returnPermits(int) calls (0.0d to 1.0d)
      Returns:
      a sampled AllocationStrategy that otherwise behaves like the delegate
    • getPermits

      public int getPermits(int desired)
      Description copied from interface: AllocationStrategy
      Try to get the permission to allocate a desired positive number of new resources. Returns the permissible number of resources which MUST be created (otherwise the internal live counter of the strategy might be off). This permissible number might be zero, and it can also be a greater number than desired, which could for example denote a minimum warmed-up size for the pool to maintain (see below). Once a resource is discarded from the pool, it must update the strategy using AllocationStrategy.returnPermits(int) (which can happen in batches or with value 1).

      For the warming up case, the typical pattern would be to call this method with a desired of zero.

      Specified by:
      getPermits in interface AllocationStrategy
      Parameters:
      desired - the desired number of new resources
      Returns:
      the actual number of new resources that MUST be created, can be 0 and can be more than desired
    • returnPermits

      public void returnPermits(int returned)
      Description copied from interface: AllocationStrategy
      Update the strategy to indicate that N resources were discarded from the Pool, potentially leaving space for N new ones to be allocated. Users MUST ensure that this method isn't called with a value greater than the number of held permits it has.

      Some strategy MIGHT throw an IllegalArgumentException if it can be determined the number of returned permits is not consistent with the strategy's limits and delivered permits.

      Specified by:
      returnPermits in interface AllocationStrategy
    • estimatePermitCount

      public int estimatePermitCount()
      Description copied from interface: AllocationStrategy
      Best-effort peek at the state of the strategy which indicates roughly how many more resources can currently be allocated. Should be paired with AllocationStrategy.getPermits(int) for an atomic permission.
      Specified by:
      estimatePermitCount in interface AllocationStrategy
      Returns:
      an ESTIMATED count of how many more resources can currently be allocated
    • permitGranted

      public int permitGranted()
      Specified by:
      permitGranted in interface AllocationStrategy
      Returns:
      a best estimate of the number of permits currently granted, between 0 and Integer.MAX_VALUE
    • permitMinimum

      public int permitMinimum()
      Description copied from interface: AllocationStrategy
      Return the minimum number of permits this strategy tries to maintain granted (reflecting a minimal size for the pool), or 0 for scale-to-zero.
      Specified by:
      permitMinimum in interface AllocationStrategy
      Returns:
      the minimum number of permits this strategy tries to maintain, or 0
    • permitMaximum

      public int permitMaximum()
      Specified by:
      permitMaximum in interface AllocationStrategy
      Returns:
      the maximum number of permits this strategy can grant in total, or Integer.MAX_VALUE for unbounded
    • warmupParallelism

      public int warmupParallelism()
      Description copied from interface: AllocationStrategy
      Return the concurrency level used when the allocator is subscribed to during the warmup phase, if any.

      The number of resources created concurrently will not exceed the value returned by warmupParallelism(). If the concurrency level is set to 1, pre-allocation of resources will be performed sequentially by subscribing to the allocator one at a time. The process waits for a resource to be created before subscribing again to the allocator. This sequence continues until all pre-allocated resources have been successfully created.

      Defaults to 1

      Specified by:
      warmupParallelism in interface AllocationStrategy
      Returns:
      The concurrency level used when the allocator is subscribed to during the warmup phase, must be positive, 1 by default