Skip to content

Offload slot calculation and cross-slot detection to I/O threads#2165

Merged
zuiderkwast merged 7 commits into
valkey-io:unstablefrom
zuiderkwast:offload-crossslot
Jun 4, 2025
Merged

Offload slot calculation and cross-slot detection to I/O threads#2165
zuiderkwast merged 7 commits into
valkey-io:unstablefrom
zuiderkwast:offload-crossslot

Conversation

@zuiderkwast

@zuiderkwast zuiderkwast commented Jun 3, 2025

Copy link
Copy Markdown
Contributor

Refactors getNodeByQuery() to be able to move the CRC16 slot calculations in I/O threads and skip many checks if slot migrations are not ongoing.

The slot calculation for a command is moved out of getNodeByQuery() into a new function clusterSlotByCommand() which is safe to call from I/O threads.

For MULTI-EXEC transactions, the slot is stored per command in the multi-state, to be able to detect cross-slot transactions on EXEC without computing the slots again.

Sorry for the large diff within getNodeByQuery(). This function is quite long and complex. I added a goto to skip parts of it, to avoid indenting a large code block. (We can do it, but it gives a larger diff to review.)

Additionally, cross-slot detection and arity check is offloaded to I/O threads. To unify the code paths for commands parsed by I/O threads and commands parsed by the main thread, the command lookup, arity check, slot lookup are moved out of processCommand() to a new prepareCommand() function that needs to be called before processCommand().

The client's read flags are used for passing information about bad arity and cross-slot. These flags are already used to convey information per command between I/O thread and main thread.

Fixes #2077
Related to #632

Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
@zuiderkwast zuiderkwast requested review from PingXie, madolson, ranshid and uriyage and removed request for madolson June 3, 2025 10:20
@codecov

codecov Bot commented Jun 3, 2025

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 83.14607% with 15 lines in your changes missing coverage. Please review.

Project coverage is 71.46%. Comparing base (3631208) to head (3031320).
Report is 4 commits behind head on unstable.

Files with missing lines Patch % Lines
src/module.c 0.00% 5 Missing ⚠️
src/server.c 73.68% 5 Missing ⚠️
src/cluster.c 96.36% 2 Missing ⚠️
src/memory_prefetch.c 0.00% 2 Missing ⚠️
src/networking.c 80.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #2165      +/-   ##
============================================
+ Coverage     71.35%   71.46%   +0.11%     
============================================
  Files           122      122              
  Lines         66178    66210      +32     
============================================
+ Hits          47222    47319      +97     
+ Misses        18956    18891      -65     
Files with missing lines Coverage Δ
src/multi.c 97.31% <100.00%> (+0.01%) ⬆️
src/script.c 87.64% <100.00%> (-0.05%) ⬇️
src/server.h 100.00% <ø> (ø)
src/networking.c 87.80% <80.00%> (+0.32%) ⬆️
src/cluster.c 90.38% <96.36%> (+0.13%) ⬆️
src/memory_prefetch.c 12.50% <0.00%> (ø)
src/module.c 9.59% <0.00%> (-0.01%) ⬇️
src/server.c 87.93% <73.68%> (-0.10%) ⬇️

... and 11 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ranshid ranshid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good, but I will probably need a 2nd look. some small comments for now

Comment thread src/cluster.c
Comment thread src/networking.c Outdated
Comment thread src/server.c Outdated
Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>

@ranshid ranshid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit - just to reduce the diff little bit.

Comment thread src/cluster.c
Comment thread src/cluster.c
Comment thread src/cluster.c
Comment thread src/cluster.c Outdated
Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>

@ranshid ranshid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

Comment thread src/cluster.c Outdated

@madolson madolson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No real concerns for me, looks good

Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
@zuiderkwast zuiderkwast merged commit 3789b29 into valkey-io:unstable Jun 4, 2025
51 checks passed
Comment thread src/server.c
@dvkashapov

Copy link
Copy Markdown
Member

Did some benchmarks, results are in related issue

@PingXie PingXie left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

sorry for being late, again :) looks great to me - just one minor comment and I think getNodeByQuery could be further simplified. thanks @zuiderkwast

Comment thread src/cluster.c
chzhoo pushed a commit to chzhoo/valkey that referenced this pull request Jun 12, 2025
…key-io#2165)

Refactors `getNodeByQuery()` to be able to move the CRC16 slot
calculations in I/O threads and skip many checks if slot migrations are
not ongoing.

The slot calculation for a command is moved out of `getNodeByQuery()`
into a new function `clusterSlotByCommand()` which is safe to call from
I/O threads.

For MULTI-EXEC transactions, the slot is stored per command in the
multi-state, to be able to detect cross-slot transactions on EXEC
without computing the slots again.

Additionally, cross-slot detection and arity check is offloaded to I/O
threads. To unify the code paths for commands parsed by I/O threads and
commands parsed by the main thread, the command lookup, arity check,
slot lookup are moved out of `processCommand()` to a new
`prepareCommand()` function that needs to be called before
`processCommand()`.

The client's read flags are used for passing information about bad arity
and cross-slot. These flags are already used to convey information per
command between I/O thread and main thread.

Fixes valkey-io#2077
Related to valkey-io#632

---------

Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
Signed-off-by: chzhoo <czawyx@163.com>
shanwan1 pushed a commit to shanwan1/valkey that referenced this pull request Jun 13, 2025
…key-io#2165)

Refactors `getNodeByQuery()` to be able to move the CRC16 slot
calculations in I/O threads and skip many checks if slot migrations are
not ongoing.

The slot calculation for a command is moved out of `getNodeByQuery()`
into a new function `clusterSlotByCommand()` which is safe to call from
I/O threads.

For MULTI-EXEC transactions, the slot is stored per command in the
multi-state, to be able to detect cross-slot transactions on EXEC
without computing the slots again.

Additionally, cross-slot detection and arity check is offloaded to I/O
threads. To unify the code paths for commands parsed by I/O threads and
commands parsed by the main thread, the command lookup, arity check,
slot lookup are moved out of `processCommand()` to a new
`prepareCommand()` function that needs to be called before
`processCommand()`.

The client's read flags are used for passing information about bad arity
and cross-slot. These flags are already used to convey information per
command between I/O thread and main thread.

Fixes valkey-io#2077
Related to valkey-io#632

---------

Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
Signed-off-by: shanwan1 <shanwan1@intel.com>
@zuiderkwast zuiderkwast deleted the offload-crossslot branch July 1, 2025 22:30
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.

Avoid recalculating cluster slot when the I/O thread has already done so

5 participants