Skip to content

introduce CycleBufferPool#3103

Open
mgravell wants to merge 2 commits into
v3from
marc/cyclebufferpool
Open

introduce CycleBufferPool#3103
mgravell wants to merge 2 commits into
v3from
marc/cyclebufferpool

Conversation

@mgravell

@mgravell mgravell commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator
  • (RESPite) add CycleBufferPool as a concept that encapsulates MemoryPool<byte> with the desired buffer growth logic
  • (SE.Redis) use the new API internally for reads and writes
  • (resp-benchmark) support -d in the benchmark
  • (SE.Redis) make this new concept configurable on the SE.Redis options
  • (SE.Redis) anything for array pool?

In addition to isolation, allowing a growth strategy improves performance when dealing with large payloads (-d 500000):

V2

dotnet run -p:TargetVer=2 -f net10.0 -c Release -- -q -c 50 -P 2 +m --queue
  -n 5000 -q -l -t GET -d 500000
### classic SE.Redis 2.13.17.28173 ###
SET:    3,564 requests per second
GET:    3,058 requests per second
SET:    1,902 requests per second
GET:    2,474 requests per second
SET:    3,136 requests per second
GET:    2,950 requests per second
SET:    4,485 requests per second
GET:    4,074 requests per second
SET:    4,831 requests per second
GET:    4,014 requests per second
SET:    5,361 requests per second
GET:    4,630 requests per second
SET:    4,966 requests per second
GET:    4,308 requests per second

V3 before this change

dotnet run -p:TargetVer=3 -f net10.0 -c Release -- -q -c 50 -P 2 +m --queue
  -n 5000 -q -l -t GET -d 500000
### classic SE.Redis 3.0.0.11234 ###
SET:    1,820 requests per second
GET:    4,454 requests per second
SET:    1,592 requests per second
GET:    2,851 requests per second
SET:    1,460 requests per second
GET:    5,032 requests per second
SET:    1,917 requests per second
GET:    4,804 requests per second
SET:    1,869 requests per second
GET:    4,814 requests per second
SET:    1,850 requests per second
GET:    4,866 requests per second

V3 after this change

dotnet run -p:TargetVer=3 -f net10.0 -c Release -- -q -c 50 -P 2 +m --queue
  -n 5000 -q -l -t GET -d 500000
### classic SE.Redis 3.0.0.11234 ###
SET:    5,974 requests per second
GET:    7,224 requests per second
SET:    5,725 requests per second
GET:    7,162 requests per second
SET:    6,617 requests per second
GET:    8,159 requests per second
SET:    5,781 requests per second
GET:    8,213 requests per second
SET:    6,736 requests per second
GET:    8,233 requests per second
SET:    6,962 requests per second
GET:    6,915 requests per second
SET:    6,368 requests per second
GET:    8,142 requests per second

…<byte> with the growth logic

- support `-d` in the benchmark
- add [SkipLocalsInit] to RESPite
@pairbit

pairbit commented Jun 17, 2026

Copy link
Copy Markdown

The idea is sound, but I'm looking at a different approach here - to allow more flexibility without hard coding specific things like the power factor into the API; thoughts? #3103

This is definitely correct. This will completely solve the memory control issue for requests, but not for responses.

I propose to add ResponseArrayPool for oversized payload.
I would also like to see it used in the Lease class.

var arrayPool = BridgeCouldBeNull?.Multiplexer.RawConfig.ResponseArrayPool ?? ArrayPool<byte>.Shared;

byte[]? oversized = arrayPool.Rent(len);
payload.CopyTo(oversized);
OnResponseFrame(prefix, new(oversized, 0, len), ref oversized);

// the lease could have been claimed by the activation code (to prevent another memcpy); otherwise, free
if (oversized is not null)
{
    arrayPool.Return(oversized);
}

#3104

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.

2 participants