Scheduler

kyo.scheduler.Scheduler
See theScheduler companion object
final class Scheduler(workerExecutor: Executor, clockExecutor: Executor, timerExecutor: ScheduledExecutorService, config: Config)

A high-performance task scheduler with adaptive concurrency control and admission regulation.

The scheduler provides a foundation for concurrent task execution with features including dynamic worker pool sizing, admission control to prevent overload, work stealing for load balancing, task preemption, and comprehensive performance monitoring.

==Worker Management==

The scheduler maintains a pool of worker threads that execute tasks. The number of workers adjusts dynamically between configured minimum and maximum bounds based on system load and performance metrics. Workers can steal tasks from each other to balance load across the pool, ensuring efficient resource utilization.

==Admission Control==

An admission regulator prevents system overload by selectively rejecting tasks when the system shows signs of congestion. The admission rate adjusts automatically based on measured queuing delays, providing natural backpressure that helps maintain system stability under varying loads.

==Concurrency Control==

A concurrency regulator continuously monitors system scheduling efficiency through sophisticated timing measurements. By analyzing scheduling delays and system load, it dynamically adjusts the worker pool size to maintain optimal performance. The regulator detects both under-utilization and thread interference, scaling the thread count up or down accordingly.

==Thread Blocking and Adaptive Concurrency==

The scheduler employs a sophisticated approach to handle thread blocking that requires no explicit signaling or special handling from tasks. Instead of treating blocking as an exceptional case, the system embraces it as a natural part of task execution through its adaptive concurrency mechanism.

At its core, the scheduler uses an ephemeral thread model where workers acquire threads from a pool only when actively processing tasks. When a thread becomes blocked, the scheduler detects this through direct thread state inspection and automatically compensates by adjusting its concurrency level. This detection-and-response cycle creates a natural overflow capacity that maintains throughput even when many threads are blocked.

The design's effectiveness lies in its transparency: tasks can freely perform blocking operations without concerning themselves with thread management. When blocking occurs, the concurrency regulator observes increased scheduling delays and responds by expanding the worker pool if possible and necessary. As blocked threads resume, the improved scheduling efficiency triggers a gradual reduction in worker count.

==Loom Integration==

The scheduler seamlessly integrates with Java's Project Loom virtual threads when available, providing enhanced scalability for I/O-bound workloads. To enable virtual threads, add the JVM argument '--add-opens=java.base/java.lang=ALL-UNNAMED' and set '-Dkyo.scheduler.virtualizeWorkers=true'. The scheduler transparently manages virtual thread creation and scheduling through the worker executor.

==Monitoring==

Comprehensive metrics about scheduler operation are exposed through JMX and optional console reporting, providing detailed insight into worker utilization, task execution, regulation decisions, and system load.

Value parameters

clockExecutor

Executor for running the internal clock

config

Configuration parameters controlling scheduler behavior

timerExecutor

Executor for running scheduled operations

workerExecutor

Executor for running worker threads

Attributes

See also

Worker for details on task execution and work stealing

Admission for admission control implementation

Concurrency for concurrency regulation details

Companion
object
Graph
Supertypes
class Object
trait Matchable
class Any

Members list

Value members

Concrete methods

def asExecutionContext: ExecutionContext

Provides a Scala ExecutionContext interface to the scheduler.

Provides a Scala ExecutionContext interface to the scheduler.

Allows using the scheduler as a drop-in replacement for Scala execution contexts while maintaining all scheduler capabilities like admission control and adaptive concurrency.

Attributes

Returns

An ExecutionContext backed by the scheduler

def asExecutor: Executor

Provides an Executor interface to the scheduler.

Provides an Executor interface to the scheduler.

Allows using the scheduler as a drop-in replacement for standard Java executors while maintaining all scheduler capabilities like admission control and adaptive concurrency.

Attributes

Returns

An Executor that submits Runnables as scheduler tasks

def asExecutorService: ExecutorService

Provides a Java ExecutorService interface to the scheduler.

Provides a Java ExecutorService interface to the scheduler.

Allows using the scheduler as a drop-in replacement for Java ExecutorService implementations while maintaining all scheduler capabilities like admission control and adaptive concurrency. This implementation provides a minimal ExecutorService that delegates task execution to the scheduler.

Note that shutdown-related operations are no-ops in this implementation:

  • shutdown() and shutdownNow() have no effect
  • isShutdown() and isTerminated() always return false
  • awaitTermination() always returns false

Attributes

Returns

An ExecutorService that submits Runnables as scheduler tasks

def flush(): Unit

Forces completion of any pending tasks on the current worker thread.

Forces completion of any pending tasks on the current worker thread.

When called from a worker thread, drains and re-submits all queued tasks before returning. Has no effect when called from non-worker threads.

Attributes

def loadAvg(): Double

Calculates the current average load across all workers.

Calculates the current average load across all workers.

Load is measured as the number of queued plus executing tasks per worker. This metric is used by the regulators to make admission and concurrency decisions.

Attributes

Returns

Average load per worker between 0.0 and worker queue capacity

def reject(): Boolean

Tests if a new task should be rejected based on current system conditions.

Tests if a new task should be rejected based on current system conditions.

The scheduler uses admission control to prevent system overload by selectively rejecting tasks when detecting signs of congestion. This method provides probabilistic load shedding using random sampling, making it suitable for one-off tasks where consistent admission decisions aren't required.

This approach works well for:

  • One-off tasks with no related operations
  • Tasks where consistent rejection isn't critical
  • High-volume scenarios where perfect distribution isn't necessary
  • Cases where no natural key exists for the task

For tasks requiring consistent admission decisions (e.g., related operations that should be handled similarly), prefer using reject(key) or reject(string) instead.

Attributes

Returns

true if the task should be rejected, false if it can be accepted

def reject(key: String): Boolean

Tests if a task with the given string key should be rejected based on current system conditions.

Tests if a task with the given string key should be rejected based on current system conditions.

This method provides consistent admission decisions by using the string's hash as a sampling key. This ensures that identical strings will receive the same admission decision at any given admission percentage, creating stable and predictable load shedding patterns.

This consistency is particularly valuable for:

  • User IDs or session identifiers to maintain consistent user experience
  • Transaction or operation IDs for related task sets
  • Service names or endpoints for targeted load shedding
  • Any scenario requiring deterministic admission control

The string-based rejection provides several benefits:

  • Related requests from the same user/session get uniform treatment
  • Retries of rejected tasks won't add load since they'll stay rejected
  • System stabilizes with a consistent subset of flowing traffic
  • Natural backpressure mechanism for distributed systems

Value parameters

key

String to use for admission decision

Attributes

Returns

true if the task should be rejected, false if it can be accepted

def reject(key: Int): Boolean

Tests if a task with the given integer key should be rejected based on current system conditions.

Tests if a task with the given integer key should be rejected based on current system conditions.

This method provides consistent admission decisions by using the integer directly as a sampling key. It guarantees that identical integers will receive the same admission decision at any given admission percentage, implemented through efficient modulo operations.

This method is particularly useful for:

  • Numeric identifiers like user IDs or request sequence numbers
  • Hash values from other sources
  • Cases where the caller has already computed a suitable numeric key
  • Performance-critical scenarios needing minimal overhead

The integer-based rejection maintains the same consistency benefits as string-based rejection:

  • Deterministic decisions for identical keys
  • Stable load shedding patterns
  • Efficient handling of related operations
  • Natural queueing behavior for rejected requests

Value parameters

key

Integer to use for admission decision

Attributes

Returns

true if the task should be rejected, false if it can be accepted

def schedule(task: Task): Unit

Schedules a task for execution by the scheduler.

Schedules a task for execution by the scheduler.

The scheduler will assign the task to an available worker based on current load and system conditions. Tasks are executed according to their priority ordering and may be preempted if they exceed their time slice.

Value parameters

task

The task to schedule for execution

Attributes

def shutdown(): Unit

Shuts down the scheduler and releases resources.

Shuts down the scheduler and releases resources.

Stops all internal threads, cancels pending tasks, and cleans up monitoring systems. The scheduler cannot be restarted after shutdown.

Attributes

def status(): Status