Skip to content

[core] Make autoscaler v1 fetch from GcsAutoscalerStateManager instead of GcsResourceManager for future GCS cleanup - #66633

Merged
rueian merged 3 commits into
ray-project:masterfrom
dancingactor:autoscaler-resource-view
Oct 24, 2026
Merged

rueian merged 3 commits into
ray-project:masterfrom
dancingactor:autoscaler-resource-view

Conversation

@dancingactor

@dancingactor dancingactor commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Description

Context

This PR migrates autoscaler v1 to read only from GcsAutoscalerStateManager, rather than the legacy path in GcsResourceManager. This enables future removal of redudant cluster resource data in GcsResourceManager (reference), significantly improving GCS performance and reducing the complexity of GCS's cluster resource view management logic. I explain this in more detail below:

GCS stores the same cluster resource availability and demand information multiple times.

  • Availability:
    • ClusterResourceManager
    • GcsResourceManager
    • GcsAutoscalerStateManager
  • Demand:
    • GcsResourceManager
    • GcsAutoscalerStateManager

GcsResourceManager is the redundant copy in both cases, so we can eventually remove it entirely. But before we can do that, we first need to remove one of its consumers — autoscaler v1 — by making it fetch the same information from GcsAutoscalerStateManager instead, which is what this PR does.

What this PR does

Autoscaler v1 currently reads resource demand and placement-group load from GcsResourceManager.

  • Resource demand: GcsAutoscalerStateManager already has an equivalent field, so we use it directly.
  • Placement-group load: GcsAutoscalerStateManager only exposed the derived pending_gang_resource_requests shape, not the raw PlacementGroupTableData that v1 needs, so we added a placement_group_load field to autoscaler.proto so GcsAutoscalerStateManager can expose it directly.

Related Issues

Related to #66718

…d of GcsResourceManager for future GCS cleanup

Signed-off-by: dancingactor <s990346@gmail.com>
@dancingactor
dancingactor requested a review from a team as a code owner October 1, 2026 17:20

@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 migrates the v1 autoscaler's resource demand and placement group load tracking from the legacy get_all_resource_usage GCS RPC to get_cluster_resource_state. It updates parse_resource_demands to parse pending_resource_requests from ClusterResourceState and adds temporary support for raw placement group load in ClusterResourceState to maintain compatibility until the v1 autoscaler is retired. Corresponding tests have been updated to reflect these changes. There are no review comments to address.

@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.

Stale Bugbot comment from a previous run.

Comment thread src/ray/protobuf/autoscaler.proto Resolved
@ray-gardener ray-gardener Bot added core Issues that should be addressed in Ray Core community-contribution Contributed by the community labels Oct 1, 2026
@rueian rueian self-assigned this Oct 6, 2026

@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 and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 5d2d9aa. Configure here.

Comment thread src/ray/protobuf/autoscaler.proto Resolved
@rueian rueian added the go add ONLY when ready to merge, run all tests label Oct 17, 2026
Comment on lines +82 to +90
request_shape = dict(request_by_count.request.resources_bundle)
# Cap each shape's own contribution rather than the running
# total, so a single shape with a huge backlog (e.g. demand for
# a resource no node type can ever provide) can't crowd out a
# different, smaller shape's demand from the vector.
count = min(
request_by_count.count, AUTOSCALER_MAX_RESOURCE_DEMAND_VECTOR_SIZE
)
demand_bundles.extend([request_shape] * count)

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.

Hi @dancingactor, could you try this test:

def test_infeasible_demand_does_not_crowd_out_feasible_demand(monkeypatch):
    monitor = monitor_module.Monitor.__new__(monitor_module.Monitor)
    monitor.gcs_client = types.SimpleNamespace()
    monitor.load_metrics = LoadMetrics()
    monitor.autoscaler = types.SimpleNamespace(config={"provider": {}})
    monitor.autoscaling_config = None
    monitor.readonly_config = None
    monitor.prom_metrics = None
    monitor.event_summarizer = None

    cluster_state = autoscaler_pb2.ClusterResourceState()
    cluster_state.node_states.add(
        node_id=bytes.fromhex("ab" * 20),
        node_ip_address="1.2.3.4",
        total_resources={"CPU": 4.0},
    )
    # 800 GPU tasks no running node can fit, then 300 CPU tasks.
    for shape, count in (({"GPU": 1.0}, 800), ({"CPU": 1.0}, 300)):
        cluster_state.pending_resource_requests.add(
            request=autoscaler_pb2.ResourceRequest(resources_bundle=shape), count=count
        )
    monkeypatch.setattr(
        monitor_module, "get_cluster_resource_state", lambda gcs_client: cluster_state
    )

    monitor.update_load_metrics()

    demand_vector = monitor.load_metrics.get_resource_demand_vector()
    assert demand_vector.count({"CPU": 1.0}) == 300

@dancingactor dancingactor Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks @rueian, I ran it, and the test fails with 200 == 300. This is because this PR changes how the autoscaler caps demand: the cap is now 1000 for all demand, regardless of whether it is feasible or infeasible.

Cap before this PR:

  • Feasible demand: 1000
  • Infeasible demand: 1000

What this PR does:

I removed the split between feasible and infeasible demand for two reasons:

  1. Autoscaler v1 doesn't need the infeasible demand list at all.
  2. GcsAutoscalerStateManager doesn't provide separate feasible and infeasible demand.

So the cap becomes:

  • All demand: 1000
  • Per resource shape: 1000

Which fix do you think is better?

  • Remove the cap completely, but the demand list might get really long
  • In autoscaler v1, split feasible and infeasible demand again just so feasible demand isn't capped by infeasible demand. It will cost some performance, but it gives feasible demand more room under the cap.
  • Increase the cap to 2000, the same total as before this PR, so the tolerance range is larger.
  • Keep the current logic as is.

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.

How about doing something like this:

shapes = [
    (
        dict(request_by_count.request.resources_bundle),
        min(request_by_count.count, AUTOSCALER_MAX_RESOURCE_DEMAND_VECTOR_SIZE),
    )
    for request_by_count in pending_resource_requests
]
for i in range(max((count for _, count in shapes), default=0)):
    demand_bundles.extend(shape for shape, count in shapes if count > i)

That makes the test pass with no GCS change and the vector still capped at 1000.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This solution makes sense, changed in 32d8078.

Verified the test passes as well, thanks!

Signed-off-by: dancingactor <s990346@gmail.com>
@rueian
rueian enabled auto-merge (squash) October 22, 2026 16:01
@rueian
rueian merged commit ce4256e into ray-project:master Oct 24, 2026
7 checks passed
@dancingactor
dancingactor deleted the autoscaler-resource-view branch October 28, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution Contributed by the community core Issues that should be addressed in Ray Core go add ONLY when ready to merge, run all tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants