Skip to content

Trim excess SDS allocation in inline command parsing#15259

Merged
sundb merged 1 commit into
redis:unstablefrom
YangboLong:inline_command_parsing
Jun 22, 2026
Merged

Trim excess SDS allocation in inline command parsing#15259
sundb merged 1 commit into
redis:unstablefrom
YangboLong:inline_command_parsing

Conversation

@YangboLong

@YangboLong YangboLong commented May 25, 2026

Copy link
Copy Markdown
Contributor

This PR is based on valkey-io/valkey#1213.

sdssplitargs() builds each argument one byte at a time via sdscatlen(), which uses greedy doubling allocation. This leaves significant unused space in each SDS string — for a 600-byte value, ~400 bytes are wasted.

Add sdsRemoveFreeSpace() after sdssplitargs() in processInlineBuffer() to trim each argument before wrapping it in an robj.

Measured with 1M SET commands with 600-byte values piped via redis-cli --pipe in inline format:

  • Before: 1,021 MB vs 655 MB for RESP (55.9% overhead)
  • After: 655 MB, matching RESP baseline

Co-authored-by: muelstefamzn muelstef@amazon.com


Note

Low Risk
Single-path memory optimization in inline parsing with no protocol or auth changes; behavior unchanged aside from lower per-argument allocation.

Overview
Inline command parsing (processInlineBuffer) now trims each argument SDS with sdsRemoveFreeSpace() right after sdssplitargs(), before arguments are wrapped in robjs.

sdssplitargs() grows strings greedily byte-by-byte, which left large unused capacity per argument (especially for big values). That extra memory showed up as much higher RSS for pipelined inline traffic than RESP; after trimming, inline usage aligns with the RESP baseline.

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

@sundb sundb requested review from ShooterIT and sundb and removed request for ShooterIT May 26, 2026 00:32
@sundb

sundb commented May 26, 2026

Copy link
Copy Markdown
Collaborator

When the argv value is small, this PR actually doesn't have any effect. But why would someone use Inline to send commands of 600 bytes?
AFAIK, inline was only used for simple manual commands.

@YangboLong

Copy link
Copy Markdown
Contributor Author

One scenario where larger inline payloads could occur is redis-cli --pipe with plaintext input, which goes through the inline parser. There is nothing prevents users from piping plaintext with larger values. That said, I don't have evidence this is common in practice. If you don't think it's worth it, I'm happy to withdraw the PR.

@sundb

sundb commented May 27, 2026

Copy link
Copy Markdown
Collaborator

One scenario where larger inline payloads could occur is redis-cli --pipe with plaintext input, which goes through the inline parser. There is nothing prevents users from piping plaintext with larger values. That said, I don't have evidence this is common in practice. If you don't think it's worth it, I'm happy to withdraw the PR.

However, I don't object to this optimization.

@fcostaoliveira

Copy link
Copy Markdown
Collaborator

This change touches performance-sensitive code paths. Adding the action:run-benchmark label will trigger the CE Performance suite so we can see the impact before merge.

@ShooterIT ShooterIT added the action:run-benchmark Triggers the benchmark suite for this Pull Request label May 30, 2026
@sundb sundb merged commit d2d3390 into redis:unstable Jun 22, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action:run-benchmark Triggers the benchmark suite for this Pull Request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants