-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hard-coded limit of nested reply depth #794
Comments
👍 |
I think it's reasonable to remove this limit, and certainly before we release v1.0.0. |
@michael-grunder That's fantastic, thanks! |
This commit removes the nested multi-bulk depth limitation of 7. We do this by switching to pointer to pointer indirection and growing the stack in chunks when needed. Initial benchmarking indicates the worse cache locality seems to be offset by the reduction in overall redisReader size, resulting in nearly identical parsing performance to the exiting master branch. See: redis#794, redis#421
I took a crack at removing the depth limitation over on my fork of hiredis. Link to the branch in question The change switches from a hard-coded stack to a dynamic one that grows as needed. I would have expected this to degrade performance (due to the worse cache locality) but it appears offset by the smaller I'd love for other people to give it a try though. If it seems reasonably stable I'll open a PR here and we can more formally discuss the change. Edit: Looks like this does incur a ~12% penalty when parsing things like pure integer replies (sample benchmark here). I'm going to rework the logic to lazily allocate our stack such that we can avoid the allocations unless we need them. Cheers, |
I'd be happy to do some testing! Would you prefer to share scripts like |
I just put together a quick and dirty repository to directly test the changes to hiredis. I cleaned it up a bit and uploaded it here The only place where I'm seeing a noticeable performance degradation is when I literally do something like this: size_t benchReader(const char *protofile) {
redisReader *rdr = redisReaderCreate();
size_t count = 0;
char buffer[32768];
size_t read;
FILE *fp = openOrAbort(protofile);
while ((read = fread(buffer, 1, sizeof(buffer), fp)) != 0) {
redisReaderFeed(rdr, buffer, read);
count += consumeReplies(rdr);
}
if (read > 0) {
redisReaderFeed(rdr, buffer, read);
count += consumeReplies(rdr);
}
redisReaderFree(rdr);
fclose(fp);
return count;
} In the above code I am manually creating a You can use the PHP script to generate your own raw protocol data: $ php resp-protogen/proto.php --count 1000000 --type multibulk --bulkleaf rand >| /tmp/mbk.1m.proto I think one can argue that the raw reader benchmark is a micro benchmark that is likely acceptable given that the slowdown fades into noise when I use hiredis as a reply parser (and especially if I'm, actually communicating with Redis). Anyway, let me know if you have any questions |
I ran the raw benchmark scripts and have placed their outputs here: The |
My apologies. This process won't really work now because it expects the protocol data to be separated by a delimiter character, which I removed after realizing that I was also bench-marking my I added the option back if you would like to use the non-raw benchmarking programs too Example usage: # Note the --delim '^' argument to proto.php
php resp-protogen/proto.php --count 100000 --type multibulk --bulkleaf rand --delim '^' >| /tmp/mbk.100k.delim.proto
./bench-master /tmp/mbk.100k.delim.proto
./bench-unlimited-depth /tmp/mbk.100k.delim.proto This specific test is where the new code is slower for me: Raw protocol parsing only integer replies Thanks for running the benchmarks on another system and please let me know if you encounter any bugs/crashes/etc. |
Oh, that's fine! I was just trying for completeness. I performed a few raw benchmark tests that will hopefully focus on your integer reply case: For me, the difference between master and |
That is interesting! Perhaps it comes down to AMD CPUs being less clever for this specific workload (I'm running a Ryzen 1800X). Given these numbers I don't think it's worth doing something more exotic (and error prone). I'll go ahead and open the PR so more people can try the change out and provide input. Thanks again for running the tests on your machine! |
Happy to help! Thanks for getting to this so quickly! |
Closing via #797 |
Hello,
Hiredis has the following restriction:
hiredis/read.c
Lines 418 to 423 in 0501c62
This is a limitation that RedisGraph can hit when processing complex but sane queries.
Could this limit be relaxed?
The text was updated successfully, but these errors were encountered: