run: cap Redis maxmemory to N% of total_system_memory before init_commands#536
Open
fcostaoliveira wants to merge 1 commit intomasterfrom
Open
run: cap Redis maxmemory to N% of total_system_memory before init_commands#536fcostaoliveira wants to merge 1 commit intomasterfrom
fcostaoliveira wants to merge 1 commit intomasterfrom
Conversation
…mands
Adds an opt-in mechanism to set Redis `maxmemory` proportionally to
the bench-server's total memory before any spec-defined init_commands
run, so workloads that previously OOM-killed the OS now hit
Redis-level OOM errors instead.
Default behaviour is unchanged: nothing is sent unless a spec field
or CLI flag asks for it. RediSearchEnterprise (and any other
downstream consumer) keeps its existing semantics.
Sources, in precedence order:
--no-maxmemory-cap force-disable for this run
--maxmemory-pct N CLI override
dbconfig.maxmemory_pct N spec-level opt-in (per-spec)
Cap formula: min(pct% * total_system_memory, total - 4 GiB), where the
4 GiB OS-reserve floor is only applied when total_system_memory is
greater than 4 GiB. On tiny instances the floor is bypassed and only
the pct cap applies. Existing non-zero `maxmemory` values are
overwritten with a WARNING log line.
Implementation:
- new helpers in redisbench_admin/run/common.py:
_get_maxmemory_pct_from_dbconfig (handles both dict and list
dbconfig formats)
_resolve_maxmemory_pct (precedence resolver)
_compute_maxmemory_cap_bytes (cap arithmetic + 4 GiB floor)
apply_maxmemory_cap (orchestrator: reads INFO
memory, logs, applies)
- execute_init_commands and run_redis_pre_steps gain an optional
`args` kwarg (default None). When set, CLI overrides are honoured;
when not, only the spec field is consulted, so the spec-driven
path works regardless of caller plumbing.
- run_local/local_db.py threads `args` through the two
run_redis_pre_steps callsites. The remote_db path keeps `args=None`
for now (spec field still fires); CLI override there is a small
follow-up.
Resolves the bench-server unresponsiveness observed when the
`search-expire-doc-10-milliseconds` spec is run on m7g.8xlarge /
m7i.8xlarge: instead of the kernel OOM-killer leaving sshd starved
and the box unreachable (terraform destroy still works, but no
result is captured), Redis now refuses writes once the cap is hit
and the bench completes with a partial-result warning.
Tests:
- 13 new unit tests in tests/test_common.py covering precedence,
cap arithmetic at 8/128 GiB and tiny instances, no-op paths,
overwrite-with-warn, and INFO memory failure modes. All pass.
- 3 pre-existing tests still need RTS_PORT (live Redis) and were
already failing on origin/master without it; not affected.
JoanFM
requested changes
Apr 28, 2026
| help="If set, before running each spec's init_commands send `CONFIG SET maxmemory <pct%% of total_system_memory>` so OS-level OOM is replaced with Redis-level OOM. Floor: leaves >=4 GiB for the OS when total > 4 GiB. Overrides `dbconfig.maxmemory_pct` from the spec. Range: (0, 100].", | ||
| ) | ||
| parser.add_argument( | ||
| "--no-maxmemory-cap", |
Contributor
There was a problem hiding this comment.
I am not sure is good to have negative logic. It is hard to keep it backwards compatible?
Contributor
There was a problem hiding this comment.
if setting None to the maxmemory-pct should be the way to remove it, and it should be the default?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an opt-in mechanism to set Redis
maxmemoryproportionally to the bench-server's total memory before any spec-definedinit_commandsrun, so workloads that previously OOM-killed the OS now hit Redis-level OOM errors instead.Three sources, in precedence order:
--no-maxmemory-cap--maxmemory-pct Ndbconfig.maxmemory_pct: NWhen none is set, nothing is sent. Existing specs and existing CI pipelines (RediSearch, RediSearchEnterprise, anyone else consuming this CLI) see no behaviour change unless they explicitly opt in.
Why
The
search-expire-doc-10-millisecondsspec on RediSearch makes the bench-server (m7g.8xlarge / m7i.8xlarge) unreachable via SSH around 140-170s into the test, withparamiko: Error reading SSH protocol bannerafterConnection closed by server. Signature is consistent with the kernel OOM-killer leaving sshd memory-starved (terraform destroy still works, but no result is captured). Reproduced on:RediSearch/RediSearch8.2 / 8.4 aarch64redislabsdev/RediSearchv8.2.9 / v8.4.5 aarch64 + v2.8.35 / v2.10.28 x86_64Setting
maxmemoryahead of time means Redis returnsOOM command not allowed when used memory > 'maxmemory'instead of letting the kernel decide. Run completes with a partial-result warning, instance stays reachable, comparison data still flows to RTS.Cap formula
The 4 GiB OS-reserve floor only kicks in when the instance has enough memory to support it. Tiny test instances (e.g. CI scratch boxes) keep the simple pct cap.
total_system_memoryis read fromINFO memoryso we don't need an instance-type catalog or/proc/meminfoSSH; it works on every supported Redis version. Failure to read it (older Redis, mocked test env) is logged and skipped — never blocks the run.If Redis already has a non-zero
maxmemoryconfigured, the new cap overwrites it with aWARNINGlog line. Spec authors who want to set their own absolute byte value ininit_commandscan do so — the explicitCONFIG SET maxmemory <bytes>they emit later will take precedence over our preface.What changes
redisbench_admin/run/args.py: new--maxmemory-pct N(int, defaultNone) and--no-maxmemory-cap(store_true) oncommon_run_args.redisbench_admin/run/common.py: new helpers:_get_maxmemory_pct_from_dbconfig— handles both dict and listdbconfigformats_resolve_maxmemory_pct— CLI > spec precedence_compute_maxmemory_cap_bytes— cap arithmetic + floorapply_maxmemory_cap— orchestrator, called as the first thing insideexecute_init_commandsexecute_init_commandsandrun_redis_pre_stepsgain an optionalargs=Nonekwarg (default preserves existing behaviour for any caller that doesn't update).redisbench_admin/run_local/local_db.py: passesargsthrough the tworun_redis_pre_stepscallsites (it already hadargsfromlocal_db_spin).run_remote/remote_db.py: not modified in this PR. The spec-field path still fires (it doesn't needargs); CLI override on the remote path is a small follow-up.Compatibility
maxmemory_pctor their pipelines pass--maxmemory-pct.Tests
13 new unit tests in
tests/test_common.py, all pass:Coverage:
dbconfigformats (dict and list)--no-maxmemory-cap/ invalid pct /INFO memoryunavailable)maxmemory3 pre-existing tests still need
RTS_PORTfor a live Redis (test_execute_init_commands,test_common_exporter_logic,test_dbconfig_keyspacelen_check) — confirmed failing identically onorigin/masterwithout that env, so unrelated to this change.Test plan after merge
tests/benchmarks/requirements.txtin RediSearch / RediSearchEnterprise to a release that includes this change.maxmemory_pct: 80to the 4search-expire-*specs only.redislabsdev/RediSearch(priv PR #241) and confirm the bench-server stays reachable.run-localto confirm noCONFIG SET maxmemoryis emitted when the field is absent.