Skip to content

benchmarking/sweperf: optionally retry ResumeActor when no worker has room - #3540

Open
Nishanth Kotla (Nishanth29) wants to merge 1 commit into
agent-substrate:mainfrom
Nishanth29:bench/sweperf-resume-retry
Open

Nishanth Kotla (Nishanth29) wants to merge 1 commit into
agent-substrate:mainfrom
Nishanth29:bench/sweperf-resume-retry

Conversation

@Nishanth29

@Nishanth29 Nishanth Kotla (Nishanth29) commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

In sweperf, a ResumeActor refused because no worker has room (ResourceExhausted or Unavailable) fails the whole task. Near capacity most tasks fail while the node keeps serving resumes at the same rate. agentsession already has a retry budget for this.

--sweperf-resume-retry-budget (default 0, off) retries those errors with 50ms-to-4s backoff until the budget runs out. The cap is above agentsession's 1s because a 1s cap sent 9.4 refused attempts per successful resume. Retried refusals go to a new ResumeActorRefused row, and only the final attempt to ResumeActor. In the task record, resume_max_ms includes the wait when a resume was retried, and capacity_retries counts the refusals. Keep the budget at 0 for goodput and host-scale sweeps.

1000 users, one c3-highcpu-192-metal node, 8 microVM workers, minutes 2-10:

Budget Tasks OK OK resumes/s ResumeActorRefused/s ResumeActor failures/s ResumeWithRetry p50 / p95
0 302 / 1,091 (27.7%) 7.70 0 4.65 5.53 / 13.95 s
60s, 1s max backoff 1,055 / 1,070 (98.6%) 7.68 72.13 (recorded as ResumeActor failures) 72.13 12.19 / 33.62 s
60s, 4s max backoff 1,066 / 1,080 (98.7%) 7.71 39.29 0.04 13.02 / 37.64 s

AI use: AI-assisted, I reviewed and tested it.

  • Tests pass
  • Docs updated

Comment on lines 906 to 909
resumeLatency := res.latency
u.awake = false
if !noopResume {
u.resumeMax = max(u.resumeMax, resumeLatency)

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.

resumeMax still takes res.latency, which is only the last (successful) attempt. With a budget set, a cycle that waited 30s for room logs a resume_max_ms of a few hundred ms in the task record, so a goodput wake gate that reads that field never sees the wait, and the 24% -> 99% shows up as good tasks. The task record's retries also leaves out these in-resume retries. Let's take res.total for resumeMax (or add a separate resume_wait_max_ms) and count the capacity retries in the task record.

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.

Done. When a resume was retried, resume_max_ms is now the client wall time including the waits, so the goodput wake gate (#3550) sees them. The task record also has capacity_retries. With the budget at 0 it's unchanged.

Comment thread docs/guides/benchmarking.md Outdated
Comment on lines +213 to +216
* `--sweperf-resume-retry-budget`: seconds a cycle keeps retrying a `ResumeActor` the fleet
had no room for (`ResourceExhausted` or `Unavailable`) with 50ms-to-1s backoff before giving
the cycle up (default `0`, off, giving the resume one attempt; set to `60` to match
`--agentsession-resume-retry-budget`).

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.

Let's say when to use this. With a budget, refusals become wake latency instead of task failures, so a run near capacity looks healthy unless ResumeWithRetry is read as the wake time. "set to 60 to match agentsession" reads like a recommended sweperf setting; for goodput or host-scale sweeps, 0 (or a budget about the size of the wake SLO) keeps overload visible.

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.

Done. The docs now say to keep it at 0 for goodput and host-scale sweeps, size it like the wake SLO otherwise, and read ResumeWithRetry as the wake time.

Comment on lines +74 to +76
resumeRetryInitialBackoff = 50 * time.Millisecond
resumeRetryMaxBackoff = time.Second
resumeRetryJitterFraction = 0.1

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.

Once the backoff reaches the 1s cap (after ~1.5s), each waiting user sends about one ResumeActor per second until the budget runs out. That is up to ~60 attempts per resume with a 60s budget, with no cap on the attempt count and no global retry budget. By Little's law, the 1000-user run (~7.7 resumes/s, 12s p50 wait) has on the order of 100 users waiting at any moment, so roughly 100 refused ResumeActor/s against 7.7 successful ones. Some of the wait we're measuring may be control-plane load that the retries add themselves. Let's put the measured attempt rate (ResumeActor failures/s) in the description, and consider a higher max backoff (a few seconds) or honoring a server retry-after hint.

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.

Raised the max backoff to 4s; agentsession stays at 1s. Retried refusals are now their own row, ResumeActorRefused. At 1000 users on one metal node, refused attempts went from 72.13/s to 39.29/s, with tasks OK 98.6% vs 98.7% and OK resumes/s 7.68 vs 7.71. ResumeWithRetry p50/p95 went from 12.19/33.62 s to 13.02/37.64 s. Table in the description. ateapi doesn't send a retry-after hint today, so that could be a follow-up.

@Nishanth29 Nishanth Kotla (Nishanth29) changed the title benchmarking/sweperf: optionally retry ResumeActor when the fleet has no room benchmarking/sweperf: optionally retry ResumeActor when no worker has room Nov 4, 2026
… room

Add --sweperf-resume-retry-budget (default 0, off). With a budget, a cycle
retries ResumeActor on ResourceExhausted or Unavailable with 50ms-to-4s
backoff until the budget runs out. Retried refusals are recorded on
ResumeActorRefused and only the final attempt on ResumeActor. In the task
record, resume_max_ms includes the wait when a resume was retried, and
capacity_retries counts the refusals.

Signed-off-by: Nishanth Kotla <nishanthkotla@google.com>

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.

LGTM

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants