Cleanup key tracking documentation and table management#8039
Cleanup key tracking documentation and table management#8039madolson merged 4 commits intoredis:unstablefrom
Conversation
|
@madolson LGTM, but i don't trust myself in this area of the code base. i find the desire to not pay the price of flushing the whole 16m slots back then on flushdb, and yet agreeing to pay it for flushall, odd. |
|
AFAIK there is no other logic there, @soloestoy was the original contributor of this so maybe he has a better idea. The old implementation was a 16 million item array of radix trees that pointed to clients. You couldn't simply just free the array, you needed to loop through it looking for radix trees, and free all those too. So even if there was just one key being tracked by one client, you had to pay a huge cost to do flushall. A side node, we probably should free the radix tree async when flushall async is used, and I intend to do some testing on that to see if it's really that important. |
|
I guess another issue is someone might have been ignoring the flush message, and relying on the invalidations to eventually get sent. |
|
Hello @madolson @oranagra , I used to do some benchmark testing on this part and hopefully I can provide some hint to the optimization of this tracking cleanup performance issue.
Therefore, as @madolson mentioned, we may need to think of the way to free tracking table async when the tracking table grows big. I was thinking about the implementation also, maybe we should provide a hardcoded value for now, if the size of tracking table grows bigger than that, we can unlink the table and freeing it in the background thread. but we need to provide the bio interface for freeing the radix tree.. Or we encourge user limiting the tracking-table-max-keys configuration? How do you think on this? Or am I missing something here? Thanks! |
|
Also I guess cleaning up tracking table and sending invalidation can be used when the configured max memory was reached? |
|
Isn't it kind of weird that we are tracking key misses? I didn't realize we were doing that. |
22c6d73 to
fd1bc78
Compare
|
@hwware I updated the code to also free the tracking table async. I also did some refactoring of bio, since it might be my least favorite code in all of Redis. @soloestoy Would still love your input about changing the behavior of flushdb also freeing the table. |
|
Hi @madolson I reread the history of tracking on flushdb and flushall, I'm sure free the About the bio refactoring, I think it's better to split this PR into two different PRs: one is the async freeing TrackingTable(with the lazyfree refactoring), the other one is the whole bio refactoring, it more clear I think. |
d964531 to
cd2019f
Compare
|
@soloestoy Thanks! I was originally going to split it, but I also thought it's easier to review the BIO refactor when it's motivated by a new callback. The total change is pretty small, so I think it's probably easier to keep them together? If you strongly disagree, I'll split them. |
|
@redis/core-team Going to take that roughly as the code is okay, but it's still a major decision. |
|
@madolson what changed since my last review of the code? just a rebase? |
|
@oranagra The table is flushed async now, the behavior altering change is the same as before. |
src/bio.c
Outdated
|
|
||
| struct lazy_free_job { | ||
| lazy_free_fn *fn; /* Function that will free the provided arguments */ | ||
| void *args[1]; /* List of arguments to be passed to the free function */ |
There was a problem hiding this comment.
Consider args[0] to make it more clear that it's dynamically allocated and it will also make the sizeof calculation more correct when allocating.
There was a problem hiding this comment.
It would be cleaner, but it throws a warning:
"warning: zero size arrays are an extension [-Wzero-length-array]". I suppose it's more portable this way. I think it's okay because we need at least one argument.
There was a problem hiding this comment.
i you can use an empty array then, like we use here:
typedef struct clientReplyBlock {
size_t size, used;
char buf[];
} clientReplyBlock;that seems the portable way to do it (C99).
There was a problem hiding this comment.
Apparently that can't exist in nested structures? I moved it out of the struct, so now we'll use a couple extra bytes but it's cleaner.
There was a problem hiding this comment.
For current bio use, it's ok, but i think it should be more generic, what should we do if we we add a new bio job, such as dump and restore keys.
Cleanup key tracking documentation, always cleanup the tracking table, and free the tracking table in an async manner when applicable.
Cleanup key tracking documentation, always cleanup the tracking table, and free the tracking table in an async manner when applicable.
This change updates how we manage CSC tracking tables to improve memory efficiency and reduce unnecessary messages to clients.
The main change is we now always clear out the tracking table when flushdb is called instead instead of just for flushall. The original motivation here was back when there was a 16 million slot table, it was expensive to clean up so we didn't want to free it. However, there needed to be some way to reclaim the memory used by the table, so flushall was for that purpose. Now that it's less expensive to clear the table, we should always do it, since we are already notifying all the clients to free out their local caches.
The secondary change here is that we also free client tracking tables asynchronously when requested. The tracking table can get very large, and could block the main thread for several seconds otherwise.