Skip to content

Conversation

@prvyk
Copy link
Contributor

@prvyk prvyk commented Jul 4, 2025

This PR implements parsing command line supplied using Redis's inline command format.

https://redis.io/docs/latest/develop/reference/protocol-spec/#inline-commands

The inline command format allows people to connect with telnet and just write commands, without requiring other command line tools. It can be useful to avoid *-cli quoting and to see raw responses. Also a very few poorly written clients may send the inline format, so it can be useful there too.

The basic implementation strategy was to take the current code, spread it out a bit, and in the same point after seeing the buffer does not contain a RESP string, try to parse as inline command: We separate the buffer to an array of ArgSlice pointing to the original buffer. Each ArgSlice pointing to a 'word' of the original command line. The first two 'words' are printed to a temporary RESP formatted string, and then we run the regular parsing on it. If a command was matched, we initialize the parseState from the ArgSlice array. The intention is to keep the main path fast and (almost) untouched, while the inline path does the necessary work to match itself to the rest of the code. It was also preferred to not implement another command matching for this.


Examples:

telnet localhost 6379

ECHO 'hello world!'

$12
hello world!

SET key "a\x0Ab"

+OK

GET key

$3
a
b

The PR implements reading the format fully (as far as I can tell, given it's not very specified), with quoting and escaping, matching even rather odd reference behaviour.

PI"NG"

+PONG

PING \"a b"

$4
\a b

"ping"

+PONG

"\x50\x49\x4E\x47"

+PONG

(In the longer run, a strict Redis compatibility mode to enable/disable some things will be useful. e.g. disable quoting/escaping the first command word)

Another thing to note is that Garnet doesn't close the connection on protocol errors (unlike redis/valkey), so it's much nicer to type there compared to references which will close the connection whenever quotes are mismatched.

@prvyk prvyk marked this pull request as draft July 4, 2025 01:46
@prvyk
Copy link
Contributor Author

prvyk commented Jul 4, 2025

The issues with the tests all have to do with readHead and endReadHead handling.

The one change to 'normal' handling was to advance endReadHead earlier (after all, Garnet already has the command and all the arguments). This handles GarnetObjectStoreDisabledError issue - otherwise, there's a case where the previous LLEN gets in the same command line as the current LLEN. That's masked by AttemptSkipLine() in main - but that code was replaced by the inline command code. I kinda forgot about it when going after the other issue, which is why it came back briefly:

The other 4 failures, happen to point at a different unrelated bug which I wasn't aware of. All were cases where GetOperationDirection() got a mixed case argument and tried to upper case it. MakeUpperCase() used bytesRead - readHead as length. When called from Parse code this is fine since there ptr is the entire read. In GetOperationDirection() ptr is just the direction argument, and its length is much smaller than the read length it gets in main. Fortunately, it accidentally still works. In this branch, it got 0 for input and didn't uppercase.

In both branches, the correct fix is to give it the actual (smaller) length which the caller already had available and not do bytesRead - readHead at all.

@prvyk prvyk marked this pull request as ready for review July 4, 2025 03:32
@prvyk prvyk force-pushed the inlinecommands branch 4 times, most recently from ece70a7 to 56d8454 Compare July 11, 2025 05:03
Copy link
Contributor

@kevin-montrose kevin-montrose left a comment

Choose a reason for hiding this comment

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

Number of points of feedback.

I'd also like a config to turn this off. Since there's some non-trivial unsafe code in here I think it'd make sense for managed Garnet instances to disable inline commands until there's been some hardening.

@prvyk
Copy link
Contributor Author

prvyk commented Jul 15, 2025

Number of points of feedback.

I'd also like a config to turn this off. Since there's some non-trivial unsafe code in here I think it'd make sense for managed Garnet instances to disable inline commands until there's been some hardening.

Added an EnableInlineCommands option based on the connection protection mechanism. Current default is to enable inline command parsing for local connections only (Loopback/socket/etc.) and ban it otherwise. I wanted to strike a balance between keeping it safe and making Garnet more easily accessible when client is not available.

@prvyk prvyk force-pushed the inlinecommands branch 5 times, most recently from 2a67384 to 82248b8 Compare July 16, 2025 12:40
@prvyk
Copy link
Contributor Author

prvyk commented Jul 17, 2025

I'd like to note that when many (normal RESP encoded) commands are sent with concurrently, as in ScatterGatherGet and GarnetObjectStoreDisabledError tests, somehow command parts get into the inline/AttemptSkipLine paths. It's something that happens in main too (put a breakpoint in RespCommand.cs:line 2778, and run the tests in Debug mode). Following this PR GarnetObjectStoreDisabledError does not exhibit this, but ScatterGatherGet yet does.

I suspect it's a bug, but diagnosing it is outside scope of this PR. What's left is working around it, the 6a1e206 and 946f0c9 changes trigged this condition and I had to workaround it each time.

@kevin-montrose kevin-montrose self-requested a review July 29, 2025 14:31
Copy link
Contributor

@kevin-montrose kevin-montrose left a comment

Choose a reason for hiding this comment

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

Some nits, but LGTM.

@prvyk prvyk force-pushed the inlinecommands branch 2 times, most recently from 856c684 to fa7dcb6 Compare August 2, 2025 14:20
@prvyk prvyk force-pushed the inlinecommands branch 3 times, most recently from d7804b0 to 524ea90 Compare August 11, 2025 14:13
@prvyk
Copy link
Contributor Author

prvyk commented Aug 26, 2025

BDN run on main:

Method Job Runtime Params Mean Error StdDev Allocated
InlinePing .NET 8 .NET 8.0 None 108.95 ns 0.141 ns 0.125 ns -
InlinePing .NET 9 .NET 9.0 None 99.40 ns 0.138 ns 0.122 ns -
Method Job Runtime Params Mean Error StdDev Allocated
Set .NET 8 .NET 8.0 None 294.9 ns 0.65 ns 0.58 ns -
SetEx .NET 8 .NET 8.0 None 383.2 ns 0.66 ns 0.62 ns -
SetNx .NET 8 .NET 8.0 None 424.8 ns 1.08 ns 0.90 ns -
SetXx .NET 8 .NET 8.0 None 432.3 ns 0.65 ns 0.51 ns -
GetFound .NET 8 .NET 8.0 None 319.8 ns 0.39 ns 0.35 ns -
GetNotFound .NET 8 .NET 8.0 None 236.0 ns 0.28 ns 0.25 ns -
Increment .NET 8 .NET 8.0 None 444.2 ns 0.55 ns 0.43 ns -
Decrement .NET 8 .NET 8.0 None 437.6 ns 0.40 ns 0.32 ns -
IncrementBy .NET 8 .NET 8.0 None 509.1 ns 9.57 ns 8.95 ns -
DecrementBy .NET 8 .NET 8.0 None 501.2 ns 2.28 ns 2.14 ns -
Set .NET 9 .NET 9.0 None 274.8 ns 2.16 ns 1.80 ns -
SetEx .NET 9 .NET 9.0 None 370.8 ns 3.06 ns 2.86 ns -
SetNx .NET 9 .NET 9.0 None 393.3 ns 0.34 ns 0.31 ns -
SetXx .NET 9 .NET 9.0 None 401.4 ns 0.35 ns 0.31 ns -
GetFound .NET 9 .NET 9.0 None 303.9 ns 0.26 ns 0.24 ns -
GetNotFound .NET 9 .NET 9.0 None 218.6 ns 0.40 ns 0.37 ns -
Increment .NET 9 .NET 9.0 None 427.7 ns 0.99 ns 0.88 ns -
Decrement .NET 9 .NET 9.0 None 438.0 ns 1.21 ns 1.01 ns -
IncrementBy .NET 9 .NET 9.0 None 488.1 ns 2.72 ns 2.27 ns -
DecrementBy .NET 9 .NET 9.0 None 497.1 ns 2.78 ns 2.60 ns -
Method Job Runtime Params Mean Error StdDev Gen0 Gen1 Gen2 Allocated
SAddRem .NET 8 .NET 8.0 ACL 172.54 μs 1.309 μs 1.160 μs 0.2441 - - 36217 B
SAddPopSingle .NET 8 .NET 8.0 ACL 84.60 μs 1.483 μs 1.315 μs - - - 6400 B
SCard .NET 8 .NET 8.0 ACL 13.14 μs 0.008 μs 0.007 μs - - - -
SMembers .NET 8 .NET 8.0 ACL 14.93 μs 0.034 μs 0.030 μs - - - -
SMoveTwice .NET 8 .NET 8.0 ACL 33.53 μs 0.463 μs 0.410 μs - - - -
SIsMember .NET 8 .NET 8.0 ACL 17.44 μs 0.032 μs 0.029 μs - - - -
SMIsMember .NET 8 .NET 8.0 ACL 21.95 μs 0.060 μs 0.056 μs - - - -
SRandMemberSingle .NET 8 .NET 8.0 ACL 18.60 μs 0.021 μs 0.016 μs - - - -
SScan .NET 8 .NET 8.0 ACL 14.73 μs 0.013 μs 0.011 μs - - - -
SUnion .NET 8 .NET 8.0 ACL 15.88 μs 0.016 μs 0.015 μs - - - -
SUnionStore .NET 8 .NET 8.0 ACL 21.20 μs 0.021 μs 0.019 μs - - - -
SInter .NET 8 .NET 8.0 ACL 16.87 μs 0.025 μs 0.024 μs - - - -
SInterStore .NET 8 .NET 8.0 ACL 22.91 μs 0.024 μs 0.021 μs - - - -
SInterCard .NET 8 .NET 8.0 ACL 22.44 μs 0.030 μs 0.028 μs - - - -
SDiff .NET 8 .NET 8.0 ACL 16.65 μs 0.026 μs 0.024 μs - - - -
SDiffStore .NET 8 .NET 8.0 ACL 19.90 μs 0.034 μs 0.030 μs - - - -
SAddRem .NET 9 .NET 9.0 ACL 155.36 μs 2.342 μs 2.076 μs 0.2441 - - 33817 B
SAddPopSingle .NET 9 .NET 9.0 ACL 75.75 μs 1.422 μs 1.330 μs 0.2441 - - 3200 B
SCard .NET 9 .NET 9.0 ACL 13.75 μs 0.028 μs 0.025 μs - - - -
SMembers .NET 9 .NET 9.0 ACL 14.81 μs 0.011 μs 0.010 μs - - - -
SMoveTwice .NET 9 .NET 9.0 ACL 32.73 μs 0.033 μs 0.027 μs - - - -
SIsMember .NET 9 .NET 9.0 ACL 16.45 μs 0.032 μs 0.027 μs - - - -
SMIsMember .NET 9 .NET 9.0 ACL 21.29 μs 0.072 μs 0.063 μs - - - -
SRandMemberSingle .NET 9 .NET 9.0 ACL 18.38 μs 0.016 μs 0.014 μs - - - -
SScan .NET 9 .NET 9.0 ACL 14.92 μs 0.026 μs 0.025 μs - - - -
SUnion .NET 9 .NET 9.0 ACL 15.75 μs 0.013 μs 0.012 μs - - - -
SUnionStore .NET 9 .NET 9.0 ACL 20.87 μs 0.030 μs 0.028 μs - - - -
SInter .NET 9 .NET 9.0 ACL 16.66 μs 0.016 μs 0.015 μs - - - -
SInterStore .NET 9 .NET 9.0 ACL 22.01 μs 0.091 μs 0.076 μs - - - -
SInterCard .NET 9 .NET 9.0 ACL 22.04 μs 0.059 μs 0.052 μs - - - -
SDiff .NET 9 .NET 9.0 ACL 16.65 μs 0.018 μs 0.017 μs - - - -
SDiffStore .NET 9 .NET 9.0 ACL 18.88 μs 0.018 μs 0.016 μs - - - -
SAddRem .NET 8 .NET 8.0 AOF 185.92 μs 3.294 μs 3.081 μs 0.2441 - - 36217 B
SAddPopSingle .NET 8 .NET 8.0 AOF 203.97 μs 3.470 μs 3.246 μs 0.2441 - - 37017 B
SCard .NET 8 .NET 8.0 AOF 46.93 μs 0.081 μs 0.063 μs - - - 3200 B
SMembers .NET 8 .NET 8.0 AOF 57.00 μs 1.116 μs 1.737 μs - - - 3200 B
SMoveTwice .NET 8 .NET 8.0 AOF 277.35 μs 2.401 μs 2.005 μs - - - 32000 B
SIsMember .NET 8 .NET 8.0 AOF 59.20 μs 0.550 μs 0.488 μs 0.0610 - - 6400 B
SMIsMember .NET 8 .NET 8.0 AOF 72.92 μs 0.476 μs 0.422 μs - - - 9600 B
SRandMemberSingle .NET 8 .NET 8.0 AOF 71.10 μs 1.387 μs 1.362 μs - - - 7200 B
SScan .NET 8 .NET 8.0 AOF 76.19 μs 1.006 μs 0.892 μs 0.1221 - - 12000 B
SUnion .NET 8 .NET 8.0 AOF 185.51 μs 3.597 μs 3.694 μs 0.7324 - - 68800 B
SUnionStore .NET 8 .NET 8.0 AOF 302.64 μs 4.379 μs 3.419 μs 1.4648 - - 156000 B
SInter .NET 8 .NET 8.0 AOF 171.16 μs 3.123 μs 2.769 μs 0.2441 - - 41600 B
SInterStore .NET 8 .NET 8.0 AOF 297.02 μs 4.841 μs 4.042 μs 0.9766 - - 114400 B
SInterCard .NET 8 .NET 8.0 AOF 174.02 μs 0.825 μs 0.644 μs 0.2441 - - 36800 B
SDiff .NET 8 .NET 8.0 AOF 177.64 μs 2.694 μs 2.388 μs 0.4883 - - 45600 B
SDiffStore .NET 8 .NET 8.0 AOF 274.86 μs 4.985 μs 5.119 μs 0.9766 - - 118400 B
SAddRem .NET 9 .NET 9.0 AOF 164.32 μs 3.134 μs 4.075 μs 0.2441 - - 33816 B
SAddPopSingle .NET 9 .NET 9.0 AOF 172.51 μs 3.354 μs 4.119 μs 0.2441 - - 37816 B
SCard .NET 9 .NET 9.0 AOF 42.83 μs 0.154 μs 0.120 μs 0.3052 - - 3200 B
SMembers .NET 9 .NET 9.0 AOF 51.19 μs 0.813 μs 0.761 μs 0.3052 - - 3200 B
SMoveTwice .NET 9 .NET 9.0 AOF 246.98 μs 4.245 μs 5.666 μs 3.1738 - - 32000 B
SIsMember .NET 9 .NET 9.0 AOF 52.55 μs 0.566 μs 0.502 μs 0.3052 - - 3200 B
SMIsMember .NET 9 .NET 9.0 AOF 61.77 μs 0.231 μs 0.205 μs 0.2441 - - 3200 B
SRandMemberSingle .NET 9 .NET 9.0 AOF 63.93 μs 0.526 μs 0.466 μs 0.6104 - - 7200 B
SScan .NET 9 .NET 9.0 AOF 70.47 μs 1.394 μs 1.954 μs 1.0986 - - 12000 B
SUnion .NET 9 .NET 9.0 AOF 171.01 μs 3.002 μs 2.507 μs 6.5918 - - 68800 B
SUnionStore .NET 9 .NET 9.0 AOF 279.83 μs 5.570 μs 5.720 μs 15.1367 - - 156800 B
SInter .NET 9 .NET 9.0 AOF 152.20 μs 2.739 μs 5.076 μs 3.9063 - - 41600 B
SInterStore .NET 9 .NET 9.0 AOF 254.47 μs 2.758 μs 2.303 μs 11.2305 - - 115200 B
SInterCard .NET 9 .NET 9.0 AOF 156.45 μs 0.904 μs 0.755 μs 3.4180 - - 36800 B
SDiff .NET 9 .NET 9.0 AOF 155.38 μs 2.346 μs 3.652 μs 4.3945 - - 45600 B
SDiffStore .NET 9 .NET 9.0 AOF 245.63 μs 4.819 μs 4.948 μs 11.2305 - - 119200 B
SAddRem .NET 8 .NET 8.0 None 168.83 μs 1.531 μs 1.357 μs 0.2441 - - 36217 B
SAddPopSingle .NET 8 .NET 8.0 None 206.53 μs 1.232 μs 1.028 μs 0.2441 - - 37017 B
SCard .NET 8 .NET 8.0 None 47.18 μs 0.813 μs 0.760 μs - - - 3200 B
SMembers .NET 8 .NET 8.0 None 55.21 μs 0.211 μs 0.176 μs - - - 3200 B
SMoveTwice .NET 8 .NET 8.0 None 260.50 μs 3.758 μs 3.515 μs - - - 32000 B
SIsMember .NET 8 .NET 8.0 None 59.11 μs 0.241 μs 0.214 μs 0.0610 - - 6400 B
SMIsMember .NET 8 .NET 8.0 None 70.30 μs 0.182 μs 0.142 μs - - - 9600 B
SRandMemberSingle .NET 8 .NET 8.0 None 68.77 μs 1.188 μs 1.111 μs - - - 7200 B
SScan .NET 8 .NET 8.0 None 74.40 μs 0.760 μs 0.635 μs 0.1221 - - 12000 B
SUnion .NET 8 .NET 8.0 None 192.12 μs 0.834 μs 0.651 μs 0.7324 - - 68800 B
SUnionStore .NET 8 .NET 8.0 None 253.06 μs 1.783 μs 1.489 μs 0.9766 - - 111200 B
SInter .NET 8 .NET 8.0 None 163.62 μs 1.981 μs 1.756 μs 0.2441 - - 41600 B
SInterStore .NET 8 .NET 8.0 None 228.91 μs 3.562 μs 2.975 μs 0.7324 - - 71200 B
SInterCard .NET 8 .NET 8.0 None 158.17 μs 0.907 μs 0.708 μs 0.2441 - - 36800 B
SDiff .NET 8 .NET 8.0 None 161.65 μs 1.006 μs 0.785 μs 0.4883 - - 45600 B
SDiffStore .NET 8 .NET 8.0 None 211.41 μs 0.940 μs 0.734 μs 0.7324 - - 75200 B
SAddRem .NET 9 .NET 9.0 None 155.33 μs 2.718 μs 2.410 μs 0.2441 - - 33817 B
SAddPopSingle .NET 9 .NET 9.0 None 159.93 μs 1.006 μs 0.785 μs 0.2441 - - 37817 B
SCard .NET 9 .NET 9.0 None 42.81 μs 0.231 μs 0.216 μs 0.3052 - - 3200 B
SMembers .NET 9 .NET 9.0 None 50.45 μs 0.983 μs 0.820 μs 0.3052 - - 3200 B
SMoveTwice .NET 9 .NET 9.0 None 219.28 μs 2.088 μs 1.953 μs 2.9297 - - 32000 B
SIsMember .NET 9 .NET 9.0 None 50.38 μs 0.358 μs 0.317 μs 0.3052 - - 3200 B
SMIsMember .NET 9 .NET 9.0 None 60.81 μs 0.218 μs 0.182 μs 0.2441 - - 3200 B
SRandMemberSingle .NET 9 .NET 9.0 None 63.80 μs 1.264 μs 1.892 μs 0.6104 - - 7200 B
SScan .NET 9 .NET 9.0 None 68.01 μs 0.597 μs 0.498 μs 1.0986 - - 12000 B
SUnion .NET 9 .NET 9.0 None 156.59 μs 1.333 μs 1.247 μs 7.0801 0.2441 0.2441 332218 B
SUnionStore .NET 9 .NET 9.0 None 226.77 μs 4.091 μs 6.607 μs 11.4746 0.4883 0.4883 112000 B
SInter .NET 9 .NET 9.0 None 139.39 μs 0.897 μs 0.839 μs 3.9063 - - 41600 B
SInterStore .NET 9 .NET 9.0 None 202.41 μs 1.387 μs 1.158 μs 6.8359 - - 72000 B
SInterCard .NET 9 .NET 9.0 None 143.45 μs 2.179 μs 3.261 μs 3.4180 - - 36800 B
SDiff .NET 9 .NET 9.0 None 140.49 μs 1.000 μs 0.781 μs 4.3945 - - 45600 B
SDiffStore .NET 9 .NET 9.0 None 194.55 μs 1.976 μs 1.849 μs 7.3242 - - 76000 B

@prvyk
Copy link
Contributor Author

prvyk commented Aug 26, 2025

BDN run on inlinecommands branch:

Method Job Runtime Params Mean Error StdDev Allocated
InlinePing .NET 8 .NET 8.0 None 99.48 ns 0.119 ns 0.112 ns -
InlinePing .NET 9 .NET 9.0 None 88.79 ns 0.156 ns 0.146 ns -
Method Job Runtime Params Mean Error StdDev Allocated
Set .NET 8 .NET 8.0 None 292.4 ns 0.37 ns 0.35 ns -
SetEx .NET 8 .NET 8.0 None 386.8 ns 0.75 ns 0.63 ns -
SetNx .NET 8 .NET 8.0 None 422.9 ns 0.43 ns 0.36 ns -
SetXx .NET 8 .NET 8.0 None 438.2 ns 1.80 ns 1.68 ns -
GetFound .NET 8 .NET 8.0 None 317.4 ns 0.26 ns 0.22 ns -
GetNotFound .NET 8 .NET 8.0 None 237.7 ns 0.30 ns 0.26 ns -
Increment .NET 8 .NET 8.0 None 447.1 ns 0.83 ns 0.74 ns -
Decrement .NET 8 .NET 8.0 None 446.6 ns 1.29 ns 1.21 ns -
IncrementBy .NET 8 .NET 8.0 None 513.9 ns 1.59 ns 1.49 ns -
DecrementBy .NET 8 .NET 8.0 None 514.8 ns 7.80 ns 7.29 ns -
Set .NET 9 .NET 9.0 None 285.2 ns 0.37 ns 0.32 ns -
SetEx .NET 9 .NET 9.0 None 371.7 ns 1.25 ns 0.97 ns -
SetNx .NET 9 .NET 9.0 None 406.3 ns 0.33 ns 0.31 ns -
SetXx .NET 9 .NET 9.0 None 414.5 ns 0.90 ns 0.80 ns -
GetFound .NET 9 .NET 9.0 None 305.3 ns 0.36 ns 0.30 ns -
GetNotFound .NET 9 .NET 9.0 None 223.0 ns 0.11 ns 0.09 ns -
Increment .NET 9 .NET 9.0 None 447.7 ns 8.97 ns 12.28 ns -
Decrement .NET 9 .NET 9.0 None 441.1 ns 3.82 ns 3.19 ns -
IncrementBy .NET 9 .NET 9.0 None 497.9 ns 8.96 ns 8.38 ns -
DecrementBy .NET 9 .NET 9.0 None 505.7 ns 3.49 ns 3.10 ns -
Method Job Runtime Params Mean Error StdDev Median Gen0 Gen1 Gen2 Allocated
SAddRem .NET 8 .NET 8.0 ACL 162.96 μs 1.099 μs 0.974 μs 162.63 μs 0.2441 - - 36217 B
SAddPopSingle .NET 8 .NET 8.0 ACL 78.97 μs 1.508 μs 1.411 μs 79.58 μs - - - 6400 B
SCard .NET 8 .NET 8.0 ACL 12.76 μs 0.012 μs 0.011 μs 12.76 μs - - - -
SMembers .NET 8 .NET 8.0 ACL 13.53 μs 0.010 μs 0.009 μs 13.53 μs - - - -
SMoveTwice .NET 8 .NET 8.0 ACL 32.27 μs 0.037 μs 0.032 μs 32.25 μs - - - -
SIsMember .NET 8 .NET 8.0 ACL 15.96 μs 0.033 μs 0.029 μs 15.96 μs - - - -
SMIsMember .NET 8 .NET 8.0 ACL 20.59 μs 0.017 μs 0.015 μs 20.60 μs - - - -
SRandMemberSingle .NET 8 .NET 8.0 ACL 17.95 μs 0.018 μs 0.016 μs 17.94 μs - - - -
SScan .NET 8 .NET 8.0 ACL 14.28 μs 0.012 μs 0.011 μs 14.28 μs - - - -
SUnion .NET 8 .NET 8.0 ACL 15.46 μs 0.034 μs 0.032 μs 15.44 μs - - - -
SUnionStore .NET 8 .NET 8.0 ACL 20.50 μs 0.018 μs 0.015 μs 20.50 μs - - - -
SInter .NET 8 .NET 8.0 ACL 16.36 μs 0.014 μs 0.011 μs 16.36 μs - - - -
SInterStore .NET 8 .NET 8.0 ACL 22.14 μs 0.165 μs 0.154 μs 22.07 μs - - - -
SInterCard .NET 8 .NET 8.0 ACL 21.94 μs 0.025 μs 0.023 μs 21.95 μs - - - -
SDiff .NET 8 .NET 8.0 ACL 16.19 μs 0.030 μs 0.028 μs 16.18 μs - - - -
SDiffStore .NET 8 .NET 8.0 ACL 18.85 μs 0.031 μs 0.026 μs 18.85 μs - - - -
SAddRem .NET 9 .NET 9.0 ACL 150.71 μs 0.783 μs 0.611 μs 150.55 μs 0.2441 - - 33817 B
SAddPopSingle .NET 9 .NET 9.0 ACL 69.84 μs 0.803 μs 0.627 μs 69.84 μs 0.2441 - - 3200 B
SCard .NET 9 .NET 9.0 ACL 13.41 μs 0.010 μs 0.009 μs 13.41 μs - - - -
SMembers .NET 9 .NET 9.0 ACL 13.41 μs 0.012 μs 0.011 μs 13.41 μs - - - -
SMoveTwice .NET 9 .NET 9.0 ACL 31.76 μs 0.046 μs 0.041 μs 31.78 μs - - - -
SIsMember .NET 9 .NET 9.0 ACL 15.96 μs 0.018 μs 0.017 μs 15.96 μs - - - -
SMIsMember .NET 9 .NET 9.0 ACL 20.15 μs 0.029 μs 0.024 μs 20.14 μs - - - -
SRandMemberSingle .NET 9 .NET 9.0 ACL 17.87 μs 0.016 μs 0.014 μs 17.87 μs - - - -
SScan .NET 9 .NET 9.0 ACL 14.47 μs 0.009 μs 0.009 μs 14.47 μs - - - -
SUnion .NET 9 .NET 9.0 ACL 15.51 μs 0.014 μs 0.011 μs 15.51 μs - - - -
SUnionStore .NET 9 .NET 9.0 ACL 20.37 μs 0.025 μs 0.021 μs 20.37 μs - - - -
SInter .NET 9 .NET 9.0 ACL 16.38 μs 0.016 μs 0.014 μs 16.39 μs - - - -
SInterStore .NET 9 .NET 9.0 ACL 21.21 μs 0.018 μs 0.015 μs 21.21 μs - - - -
SInterCard .NET 9 .NET 9.0 ACL 21.26 μs 0.023 μs 0.021 μs 21.26 μs - - - -
SDiff .NET 9 .NET 9.0 ACL 16.02 μs 0.018 μs 0.017 μs 16.02 μs - - - -
SDiffStore .NET 9 .NET 9.0 ACL 18.38 μs 0.012 μs 0.011 μs 18.37 μs - - - -
SAddRem .NET 8 .NET 8.0 AOF 180.64 μs 3.605 μs 3.703 μs 181.26 μs 0.2441 - - 36216 B
SAddPopSingle .NET 8 .NET 8.0 AOF 191.87 μs 2.526 μs 2.239 μs 192.45 μs 0.2441 - - 37017 B
SCard .NET 8 .NET 8.0 AOF 48.13 μs 0.356 μs 0.316 μs 48.13 μs - - - 3200 B
SMembers .NET 8 .NET 8.0 AOF 53.98 μs 0.173 μs 0.154 μs 53.92 μs - - - 3200 B
SMoveTwice .NET 8 .NET 8.0 AOF 277.27 μs 0.764 μs 0.596 μs 277.28 μs - - - 32000 B
SIsMember .NET 8 .NET 8.0 AOF 62.43 μs 0.968 μs 0.906 μs 62.47 μs - - - 6400 B
SMIsMember .NET 8 .NET 8.0 AOF 71.19 μs 0.685 μs 0.608 μs 71.12 μs - - - 9600 B
SRandMemberSingle .NET 8 .NET 8.0 AOF 69.56 μs 0.586 μs 0.548 μs 69.33 μs - - - 7200 B
SScan .NET 8 .NET 8.0 AOF 73.44 μs 0.610 μs 0.509 μs 73.25 μs 0.1221 - - 12000 B
SUnion .NET 8 .NET 8.0 AOF 200.31 μs 3.958 μs 5.006 μs 197.59 μs 0.7324 - - 68800 B
SUnionStore .NET 8 .NET 8.0 AOF 327.92 μs 5.439 μs 4.822 μs 328.96 μs 1.4648 - - 156000 B
SInter .NET 8 .NET 8.0 AOF 170.43 μs 1.290 μs 1.077 μs 170.26 μs 0.2441 - - 41600 B
SInterStore .NET 8 .NET 8.0 AOF 287.63 μs 5.618 μs 5.255 μs 285.49 μs 0.9766 - - 114400 B
SInterCard .NET 8 .NET 8.0 AOF 173.72 μs 0.836 μs 0.653 μs 173.73 μs 0.2441 - - 36800 B
SDiff .NET 8 .NET 8.0 AOF 181.56 μs 2.994 μs 2.801 μs 180.55 μs 0.4883 - - 45600 B
SDiffStore .NET 8 .NET 8.0 AOF 270.03 μs 2.090 μs 1.632 μs 270.46 μs 0.9766 - - 118400 B
SAddRem .NET 9 .NET 9.0 AOF 157.09 μs 3.029 μs 3.938 μs 155.23 μs 0.2441 - - 33816 B
SAddPopSingle .NET 9 .NET 9.0 AOF 165.01 μs 3.258 μs 4.002 μs 164.09 μs 0.2441 - - 37816 B
SCard .NET 9 .NET 9.0 AOF 44.21 μs 0.481 μs 0.450 μs 44.24 μs 0.3052 - - 3200 B
SMembers .NET 9 .NET 9.0 AOF 50.79 μs 0.815 μs 0.762 μs 50.55 μs 0.3052 - - 3200 B
SMoveTwice .NET 9 .NET 9.0 AOF 247.60 μs 1.745 μs 1.457 μs 247.77 μs 2.9297 - - 32000 B
SIsMember .NET 9 .NET 9.0 AOF 51.18 μs 0.673 μs 0.526 μs 51.10 μs 0.3052 - - 3200 B
SMIsMember .NET 9 .NET 9.0 AOF 61.53 μs 0.467 μs 0.437 μs 61.42 μs 0.2441 - - 3200 B
SRandMemberSingle .NET 9 .NET 9.0 AOF 63.07 μs 1.017 μs 0.794 μs 63.06 μs 0.6104 - - 7200 B
SScan .NET 9 .NET 9.0 AOF 67.59 μs 0.506 μs 0.449 μs 67.51 μs 1.0986 - - 12000 B
SUnion .NET 9 .NET 9.0 AOF 169.70 μs 0.781 μs 0.610 μs 169.66 μs 6.5918 - - 68800 B
SUnionStore .NET 9 .NET 9.0 AOF 282.74 μs 5.430 μs 5.079 μs 283.15 μs 16.1133 0.9766 0.9766 156801 B
SInter .NET 9 .NET 9.0 AOF 157.38 μs 3.126 μs 4.866 μs 155.34 μs 3.9063 - - 41600 B
SInterStore .NET 9 .NET 9.0 AOF 253.53 μs 3.093 μs 2.583 μs 253.45 μs 11.2305 - - 115200 B
SInterCard .NET 9 .NET 9.0 AOF 154.06 μs 1.409 μs 1.177 μs 153.79 μs 3.4180 - - 36800 B
SDiff .NET 9 .NET 9.0 AOF 155.17 μs 2.319 μs 2.381 μs 154.95 μs 4.3945 - - 45600 B
SDiffStore .NET 9 .NET 9.0 AOF 247.40 μs 4.024 μs 3.360 μs 246.53 μs 11.2305 - - 119200 B
SAddRem .NET 8 .NET 8.0 None 165.42 μs 1.194 μs 0.997 μs 165.62 μs 0.2441 - - 36217 B
SAddPopSingle .NET 8 .NET 8.0 None 169.41 μs 2.333 μs 2.068 μs 168.70 μs 0.2441 - - 37017 B
SCard .NET 8 .NET 8.0 None 47.01 μs 0.897 μs 0.959 μs 46.61 μs - - - 3200 B
SMembers .NET 8 .NET 8.0 None 53.08 μs 0.144 μs 0.120 μs 53.04 μs - - - 3200 B
SMoveTwice .NET 8 .NET 8.0 None 252.50 μs 3.395 μs 3.010 μs 251.77 μs - - - 32000 B
SIsMember .NET 8 .NET 8.0 None 59.37 μs 0.230 μs 0.192 μs 59.30 μs 0.0610 - - 6400 B
SMIsMember .NET 8 .NET 8.0 None 69.71 μs 0.337 μs 0.281 μs 69.65 μs - - - 9600 B
SRandMemberSingle .NET 8 .NET 8.0 None 68.21 μs 0.747 μs 0.663 μs 68.15 μs - - - 7200 B
SScan .NET 8 .NET 8.0 None 74.11 μs 0.447 μs 0.396 μs 74.19 μs 0.1221 - - 12000 B
SUnion .NET 8 .NET 8.0 None 174.26 μs 0.832 μs 0.817 μs 174.03 μs 0.7324 - - 68800 B
SUnionStore .NET 8 .NET 8.0 None 252.73 μs 5.003 μs 5.353 μs 250.52 μs 0.9766 - - 111200 B
SInter .NET 8 .NET 8.0 None 156.39 μs 1.569 μs 1.391 μs 155.75 μs 0.2441 - - 41600 B
SInterStore .NET 8 .NET 8.0 None 224.96 μs 3.069 μs 2.721 μs 223.72 μs 0.7324 - - 71200 B
SInterCard .NET 8 .NET 8.0 None 160.55 μs 1.472 μs 1.229 μs 160.78 μs 0.2441 - - 36800 B
SDiff .NET 8 .NET 8.0 None 161.00 μs 1.504 μs 1.333 μs 160.45 μs 0.4883 - - 45600 B
SDiffStore .NET 8 .NET 8.0 None 219.32 μs 1.596 μs 1.333 μs 218.86 μs 0.7324 - - 75200 B
SAddRem .NET 9 .NET 9.0 None 143.58 μs 0.537 μs 0.419 μs 143.53 μs 0.2441 - - 33817 B
SAddPopSingle .NET 9 .NET 9.0 None 157.39 μs 2.554 μs 2.264 μs 156.63 μs 0.2441 - - 37817 B
SCard .NET 9 .NET 9.0 None 42.72 μs 0.745 μs 0.581 μs 42.40 μs 0.3052 - - 3200 B
SMembers .NET 9 .NET 9.0 None 49.34 μs 0.235 μs 0.209 μs 49.34 μs 0.3052 - - 3200 B
SMoveTwice .NET 9 .NET 9.0 None 225.70 μs 4.381 μs 6.282 μs 221.96 μs 2.9297 - - 32000 B
SIsMember .NET 9 .NET 9.0 None 51.64 μs 0.618 μs 0.578 μs 51.56 μs 0.3052 - - 3200 B
SMIsMember .NET 9 .NET 9.0 None 60.80 μs 0.224 μs 0.199 μs 60.74 μs 0.3052 - - 3200 B
SRandMemberSingle .NET 9 .NET 9.0 None 62.83 μs 0.259 μs 0.318 μs 62.74 μs 0.6104 - - 7200 B
SScan .NET 9 .NET 9.0 None 68.71 μs 0.491 μs 0.435 μs 68.90 μs 1.0986 - - 12000 B
SUnion .NET 9 .NET 9.0 None 154.37 μs 1.445 μs 1.281 μs 154.20 μs 7.0801 0.2441 0.2441 -
SUnionStore .NET 9 .NET 9.0 None 229.72 μs 2.638 μs 3.866 μs 228.92 μs 11.4746 0.4883 0.4883 112001 B
SInter .NET 9 .NET 9.0 None 137.13 μs 0.756 μs 0.670 μs 137.28 μs 3.9063 - - 41600 B
SInterStore .NET 9 .NET 9.0 None 204.58 μs 2.694 μs 2.520 μs 204.09 μs 7.5684 0.4883 0.4883 72000 B
SInterCard .NET 9 .NET 9.0 None 144.56 μs 0.965 μs 1.072 μs 144.25 μs 3.4180 - - 36800 B
SDiff .NET 9 .NET 9.0 None 138.85 μs 1.527 μs 1.429 μs 138.52 μs 4.3945 - - 45600 B
SDiffStore .NET 9 .NET 9.0 None 211.96 μs 1.998 μs 1.771 μs 211.57 μs 7.3242 - - 76000 B

@kevin-montrose
Copy link
Contributor

kevin-montrose commented Sep 2, 2025

Variance looks fine.

Merge latest and get a clean set of checks and I'll merge.


After some discussion in this week's standup, I'm going to wait for @badrishc to weigh in. LGTM however.

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