Skip to content

Improve time complexity of streamMoveIdmpKeys() in asmTriggerBackgroundTrim()#15000

Open
ShubhamTaple wants to merge 4 commits intoredis:unstablefrom
ShubhamTaple:improve-stream_idmp_keys-time-complexity
Open

Improve time complexity of streamMoveIdmpKeys() in asmTriggerBackgroundTrim()#15000
ShubhamTaple wants to merge 4 commits intoredis:unstablefrom
ShubhamTaple:improve-stream_idmp_keys-time-complexity

Conversation

@ShubhamTaple
Copy link
Copy Markdown
Contributor

@ShubhamTaple ShubhamTaple commented Apr 5, 2026

Fixes #15001

Problem

In PR #14897 streamMoveIdmpKeys() was implemented such that it takes in int slot as input parameter and iterates over server.db[0].stream_idmp_keys and moves the keys which belong to slot into stream_idmp_keys.

Therefore asmTriggerBackgroundTrim() was calling streamMoveIdmpKeys() for each slot in trim ranges.

Time Complexity

Lets say number of slots be S (it could be 16,384 in worst case)
and let K be number of keys in server.db[0].stream_idmp_keys
then the total time complexity would be O(S x K)

Suggested Fix

we have changed the implementation of streamMoveIdmpKeys() such that it now takes in slotRangeArray *slots as an input parameter and iterates over server.db[0].stream_idmp_keys once, catching all the keys which fall in the slots range and moving them to stream_idmp_keys

Therefore asmTriggerBackgroundTrim() would now call streamMoveIdmpKeys() just once.

Time Complexity

say R is number of ranges in slots and let K be number of keys in server.db[0].stream_idmp_keys
then the total time complexity would be O(R x K)

since O(R x K) is better than O(S x K) because number of slots would almost always be greater than number of ranges in slotRangeArray *slots
(for a single merged range like 0–16383, R = 1 but S = 16 384).


Note

Medium Risk
Touches atomic slot migration background trimming and stream IDMP tracking, where mistakes could leave stale IDMP entries on the wrong node or delete/miss entries during slot cleanup. Change is localized but affects correctness under multi-range migrations.

Overview
Improves ASM background trimming performance by changing streamMoveIdmpKeys to accept a slotRangeArray and move all matching stream IDMP entries in a single scan instead of being called once per slot.

Updates asmTriggerBackgroundTrim() to invoke this new multi-range version once per trim job, and adds unit tests covering multi-range/disjoint-range migrations to ensure IDMP PID tracking and dedup behavior remain correct on both source and destination.

Reviewed by Cursor Bugbot for commit 23c5137. Bugbot is set up for automated code reviews on this repo. Configure here.

@skaslev skaslev requested review from sggeorgiev, sundb and tezc April 15, 2026 07:18
@tezc
Copy link
Copy Markdown
Collaborator

tezc commented Apr 15, 2026

I don't know about idmp feature but PR makes sense to me.

Btw, how many keys do we expect in this dict? any rough guesses? @sggeorgiev
I wonder if this is something that may cause a latency spike during ASM.

Also, I couldn't find a test with idmp keys & asm (maybe I'm mistaken). Perhaps, we may add it as well.

@sggeorgiev
Copy link
Copy Markdown
Collaborator

Looks good to me, the optimization makes sense. Regarding the expected number of keys in stream_idmp_keys — it depends on the number of streams with idempotent producers active, so it's typically not huge, but it can grow under heavy usage.

@tezc
Copy link
Copy Markdown
Collaborator

tezc commented Apr 15, 2026

@ShubhamTaple could you please add a test for this? Let's be sure we cover those lines.

@sundb sundb changed the title [fix] Bug Improve time complexity of streamMoveIdmpKeys() in asmTriggerBackgroundTrim() Improve time complexity of streamMoveIdmpKeys() in asmTriggerBackgroundTrim() Apr 15, 2026
@ShubhamTaple
Copy link
Copy Markdown
Contributor Author

@tezc sure I will add a test

@ShubhamTaple
Copy link
Copy Markdown
Contributor Author

Changes done in latest commit

Note: The above experimental flags are removed to enable testing

Comment thread src/commands/sflush.json Outdated
…IMENTAL tag from sflush.json and tcl"

This reverts commit f57ef33.

Revert test using sflush
@ShubhamTaple
Copy link
Copy Markdown
Contributor Author

  • Reverted last commit (SFLUSH tests)

  • Added 2 tests to test the implementation (These tests use the ASM migration to trigger bgtrim)

  • Test 1: disjoint ranges with in-range gap + far-slot; dedup on dest and source
    Verifies background trim when a single migration IMPORT trims two non-adjacent slot ranges in one batch. Ensures stream_idmp_keys / IDMP state stays correct for streams on migrated slots, streams in the gap between ranges and a far slot still on the source, matching slotRangeArray union behavior after streamMoveIdmpKeys uses the full range list in one pass.

  • Test 2: many streams, outer ranges migrated, inner + high slots remain
    Verifies the same path with many IDMP streams across the shard: only outer migrated ranges leave the source, while inner slots and high slots remains. Confirms selective stream_idmp_keys handling vs a larger dict when multiple ranges are trimmed together, not accidentally clearing or losing IDMP tracking for keys that should remain on the source.

@tezc
Copy link
Copy Markdown
Collaborator

tezc commented Apr 18, 2026

@sggeorgiev @sundb could you review the tests? I'm not qualified to review it.

@sundb
Copy link
Copy Markdown
Collaborator

sundb commented Apr 20, 2026

@sggeorgiev do we plan to change stream_idmp_keys from dict to kvstore to make it distributed by slot?

@sggeorgiev
Copy link
Copy Markdown
Collaborator

No. I don't plan to change it. stream_idmp_keys only holds the few streams actively using IDMP, so N is tiny. Kvstore's wins (per-slot rehashing, defrag, slot scans) need large N to matter, and in non-cluster mode it's just a dict with extra overhead. The only upside — using kvstoreMoveDict in ASM trim — is cosmetic at this scale, and the change would touch SWAPDB, tempDb, RDB load, lazyfree, and ASM paths for no measurable gain.

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.

[BUG] High time complexity of streamMoveIdmpKeys() in asmTriggerBackgroundTrim()

4 participants