Skip to content

[Data] Backlog-aware Actor Autoscaler - #66035

Merged
goutamvenkat-anyscale merged 7 commits into
ray-project:masterfrom
rayhhome:port-backlog-aware
Sep 22, 2026
Merged

goutamvenkat-anyscale merged 7 commits into
ray-project:masterfrom
rayhhome:port-backlog-aware

Conversation

@rayhhome

@rayhhome rayhhome commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Description

This PR implements BacklogAwareActorAutoscaler, the backlog-aware actor-pool autoscaler. Where DefaultActorAutoscaler sizes the upscale delta proportionally to the pool's current size, this autoscaler sizes it from the work already visible: it converts the operator's enqueued input blocks into a task count, adds the in-flight tasks, and solves for the pool size that brings utilization back under the upscaling threshold in a single step.

RAY_DATA_ACTOR_AUTOSCALER=DEFAULT restores the previous autoscaler.

Additional information

Adds backlog_aware_actor_autoscaler.py and registers BACKLOG_AWARE in a new ActorAutoscalerVersion, following the RAY_DATA_CLUSTER_AUTOSCALER precedent.

Enabling it also requires taking a second variable: DEFAULT_ACTOR_POOL_MAX_UPSCALING_DELTA now defaults to None. If we keep the old value of 1, this cap will truncate every scaling decision to a single actor, which would make the backlog-derived delta unobservable.

rayhhome and others added 2 commits September 9, 2026 13:46
Adds `BacklogAwareActorAutoscaler`, which sizes an actor pool off in-flight
tasks plus the tasks the enqueued input backlog will turn into, instead of
scaling proportionally to the pool's current utilization. Selected via
`RAY_DATA_ACTOR_AUTOSCALER=BACKLOG_AWARE`; the default stays
`DefaultActorAutoscaler`.

Ported from RayTurbo's `RayTurboActorAutoscaler`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Sirui Huang <ray.huang@anyscale.com>
Adds `BacklogAwareActorAutoscaler`, which sizes an actor pool off in-flight
tasks plus the tasks the enqueued input backlog will turn into, instead of
scaling proportionally to the pool's current utilization. Selected via
`RAY_DATA_ACTOR_AUTOSCALER=BACKLOG_AWARE`; the default stays
`DefaultActorAutoscaler`.

Ported from RayTurbo's `RayTurboActorAutoscaler`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Sirui Huang <ray.huang@anyscale.com>
@rayhhome rayhhome self-assigned this Sep 9, 2026
@rayhhome rayhhome added data Ray Data-related issues go add ONLY when ready to merge, run all tests labels Sep 9, 2026
@rayhhome
rayhhome marked this pull request as ready for review September 9, 2026 21:35
@rayhhome
rayhhome requested a review from a team as a code owner September 9, 2026 21:35
Copilot AI lite review requested due to automatic review settings September 9, 2026 21:35

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new BacklogAwareActorAutoscaler that sizes the actor pool based on the enqueued input backlog rather than just current utilization, allowing the pool to scale up to the required size in a single step. It also adds configuration options to select the autoscaler version via an environment variable and includes comprehensive unit tests. The review feedback highlights several code quality improvements, including removing an unused logging import and logger instance, removing a redundant override of _compute_downscale_delta, and correcting the return type annotation of _estimate_expected_tasks from float to int.

Comment thread python/ray/data/_internal/actor_autoscaler/backlog_aware_actor_autoscaler.py Outdated
Comment thread python/ray/data/_internal/actor_autoscaler/backlog_aware_actor_autoscaler.py Outdated
Comment thread python/ray/data/_internal/actor_autoscaler/backlog_aware_actor_autoscaler.py Outdated
Comment on lines +67 to +69
def _estimate_expected_tasks(
op_state: "OpState",
) -> float:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The function _estimate_expected_tasks returns an int (since math.ceil returns an int in Python 3), but its return type is annotated as float. Please update the return type annotation to int.

Suggested change
def _estimate_expected_tasks(
op_state: "OpState",
) -> float:
def _estimate_expected_tasks(
op_state: "OpState",
) -> int:

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is opt-in, well-scoped to the actor autoscaler internals, and includes targeted test coverage, with only a minor type-annotation nit noted.

Pull request overview

Ports an internal backlog-aware actor-pool autoscaler to open source Ray Data, enabling opt-in scaling decisions based on observed backlog (enqueued input blocks) plus in-flight tasks, selected via RAY_DATA_ACTOR_AUTOSCALER=BACKLOG_AWARE.

Changes:

  • Add BacklogAwareActorAutoscaler, computing scale-up deltas from backlog + in-flight tasks to reach the target utilization threshold in one step.
  • Add unit tests covering backlog-derived sizing, budget/allocation constraints, and create_actor_autoscaler version selection.
  • Register the new autoscaler version behind RAY_DATA_ACTOR_AUTOSCALER and add a Bazel py_test target.
File summaries
File Description
python/ray/data/tests/test_backlog_aware_actor_autoscaler.py New tests for backlog-aware scaling behavior and env-based autoscaler selection.
python/ray/data/BUILD.bazel Adds Bazel py_test target for the new test module.
python/ray/data/_internal/actor_autoscaler/backlog_aware_actor_autoscaler.py Introduces the backlog-aware autoscaler implementation and backlog→task estimation helper.
python/ray/data/_internal/actor_autoscaler/init.py Adds ActorAutoscalerVersion and selects autoscaler implementation via RAY_DATA_ACTOR_AUTOSCALER.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +67 to +69
def _estimate_expected_tasks(
op_state: "OpState",
) -> float:
…t-backlog-aware

# Conflicts:
#	python/ray/data/_internal/actor_autoscaler/backlog_aware_actor_autoscaler.py
@rayhhome rayhhome changed the title [Data] Port Backlog-aware Actor Autoscaler [Data] Backlog-aware Actor Autoscaler Sep 10, 2026
Signed-off-by: Sirui Huang <ray.huang@anyscale.com>
Comment thread python/ray/data/_internal/actor_autoscaler/__init__.py
Per review, there is little reason to ship it behind an opt-in.
DEFAULT_ACTOR_AUTOSCALER_VERSION becomes BACKLOG_AWARE and
DEFAULT_ACTOR_POOL_MAX_UPSCALING_DELTA becomes None. The cap truncated every
scaling decision to one actor, which would leave the new default's
backlog-derived delta unobservable. Both now match the internal
implementation.

Also drops the now-stale docstring NOTE and the unused module logger, and
corrects _estimate_expected_tasks to -> int (math.ceil returns int).

RAY_DATA_ACTOR_AUTOSCALER=DEFAULT restores the previous autoscaler.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Sirui Huang <ray.huang@anyscale.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 39715ff. Configure here.

# ceil(num enqueued blocks / avg_inputs_per_task)
#
avg_input_blocks_per_task = op_state.op.metrics.average_num_inputs_per_task or 1
return math.ceil(op_state.total_enqueued_input_blocks() / avg_input_blocks_per_task)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unknown average over-scales actor pool

Medium Severity

_estimate_expected_tasks treats a missing average_num_inputs_per_task as one block per task. That metric stays None until the first task finishes, so a queued map_batches workload is counted as far more tasks than it will become. With BACKLOG_AWARE and an uncapped actor_pool_max_upscaling_delta now the defaults, the first scale-up can launch a large burst of actors that later have to be shed one at a time.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 39715ff. Configure here.

@goutamvenkat-anyscale
goutamvenkat-anyscale merged commit 1150d1b into ray-project:master Sep 22, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data Ray Data-related issues go add ONLY when ready to merge, run all tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants