Skip to content

[History Server] Tune CPU, memory, and event logging for cold loads - #5095

Open
Future-Outlier wants to merge 8 commits into
ray-project:masterfrom
Future-Outlier:historyserver-cold-load-cpu
Open

[History Server] Tune CPU, memory, and event logging for cold loads#5095
Future-Outlier wants to merge 8 commits into
ray-project:masterfrom
Future-Outlier:historyserver-cold-load-cpu

Conversation

@Future-Outlier

@Future-Outlier Future-Outlier commented Aug 6, 2026

Copy link
Copy Markdown
Member

Why

Cold-loading large sessions is CPU- and memory-intensive. A 500m CPU limit throttles loads, while one Info log per event adds avoidable work and noise.

  • CPU: keep the 500m request and leave the limit to operators. One 50k-task session, five randomized reads per setting: median 84s → 34s.

    xychart-beta
        title "Cold load — before vs after"
        x-axis ["Before: 500m limit", "After: no limit"]
        y-axis "Cold-load time (seconds)" 0 --> 100
        bar [84, 34]
    
    Loading
  • Per-event logging: move Info to Debug. Separate 50k-task runs measured 97.9s → 85.3s (~13%); these runs were not paired, so this is supporting evidence rather than an isolated causal estimate.

    xychart-beta
        title "Per-event logging — observed cold-load time"
        x-axis ["Before: Info", "After: Debug"]
        y-axis "Cold-load time (seconds)" 0 --> 110
        bar [97.9, 85.3]
    
    Loading
  • Memory: use a 2Gi request, an 8Gi encoded-cache soft bound, and a 12Gi limit in all standalone examples. This leaves room for roughly one 100k-task decode; larger concurrent reads still need workload-specific tuning.

    History Server cold-load time and memory peak by session size

Raw measurements and reproduction scripts.

Checks

  • History Server build and race tests
  • E2E package compile
  • Manual Kind benchmarks

Loading a dead session is CPU-bound, but the sample manifest sets only
`limits.cpu: "500m"`, so Kubernetes pins requests there too and the load
saturates the quota for its entire duration. Measured on kind across 13 runs,
the container sat at 0.42-0.50 cores every time.

Raising the limit to 4 (requests stay at 500m, so scheduling cost is unchanged):

| tasks in session | 500m | 4 cores |
|---|---|---|
| 50,000 | 97.9s | 30.5s |
| 100,000 | 907.3s | 62.7s |

This also removes what looked like superlinear degradation past 50k tasks: at
500m the per-task cost went from 1.96ms to 9.07ms between 50k and 100k, while at
4 cores it is flat (0.61ms and 0.63ms). The load uses ~1.2 cores on average and
peaks at ~2.2, because Go's GC runs concurrently and needs cores of its own.

The second change drops the per-event log line in storeEvent to Debug. It runs
once per event, so a 100k-task session writes ~436,000 INFO lines per cold load,
and the binary never calls logrus.SetLevel, so there is no way to turn it off.
Worth ~13% of load time at 50k tasks (97.9s -> 85.3s).
@Future-Outlier

Copy link
Copy Markdown
Member Author

The two red checks are pre-existing on master, not from this PR.

ray-operator/controllers/ray/rayservice_controller_unit_test.go:2637 calls record.NewFakeRecorder(10), but the file's import block only has k8s.io/client-go/tools/events — every other recorder in that file is events.*. So go vet ./ray-operator/... fails at master (72b9767) with undefined: record, which is what both "Build Operator Binaries" and "Lint (pre-commit)" are reporting. It looks like a semantic merge conflict between two PRs that each passed on their own.

This PR only touches historyserver/, and "Build historyserver" passes.

Comment thread historyserver/config/historyserver.yaml Outdated
Signed-off-by: Future-Outlier <eric901201@gmail.com>
Comment thread historyserver/config/historyserver.yaml
Signed-off-by: Future-Outlier <eric901201@gmail.com>
@Future-Outlier Future-Outlier changed the title [History Server] Fix cold-load CPU starvation and per-event logging [History Server] Tune CPU, memory, and event logging for cold loads Aug 10, 2026
Signed-off-by: Future-Outlier <eric901201@gmail.com>
Signed-off-by: Future-Outlier <eric901201@gmail.com>
Signed-off-by: Future-Outlier <eric901201@gmail.com>
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.

4 participants