-
Notifications
You must be signed in to change notification settings - Fork 696
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
Replace dict with new hashtable: sorted set datatype #1427
Conversation
d2d854d
to
6a8ee44
Compare
Great! You could mark it as not draft then. :) We use the top comment and PR title for the final commit message when it gets merged, so you could update those to concisely describe the change (i.e. like a commit message). It's late in my time zone so I'll look tomorrow. |
6a8ee44
to
382d0ba
Compare
382d0ba
to
37811f6
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## unstable #1427 +/- ##
============================================
- Coverage 70.83% 70.75% -0.09%
============================================
Files 120 120
Lines 64911 64959 +48
============================================
- Hits 45982 45962 -20
- Misses 18929 18997 +68
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks awesome. Just a few nits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great work @SoftlyRaining !
Some minor comments and I feel somewhat uncomfortable about the way we implemented the union.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just fix the naming converion (compareNodeScoreEle -> zslCompareNodeScoreEle, etc.). Then I think it's good to merge.
I don't really get why you want to delete zslGetRank
. If it's an optimization beyond the replacement of dict, then it can as well be a follow up, right? As you want.
b87e508
to
e35c608
Compare
I poked around and found that all uses of zslGetRank could more efficiently use zslGetRankByNode, and it became dead code. I already made the revision at any rate but you're right, it might've been a separate small cleanup PR 😅 |
Signed-off-by: Rain Valentine <[email protected]>
Signed-off-by: Rain Valentine <[email protected]>
Signed-off-by: Rain Valentine <[email protected]>
…etRank Signed-off-by: Rain Valentine <[email protected]>
e35c608
to
6644ac5
Compare
@SoftlyRaining My only concern is a potential small degradation in performance of zcount and zlexcount. can we just make sure to verify we have no impact on these operations? |
I will remove that aspect of the change so it can be more thoroughly investigated and benchmarked as a separate PR. I'd prefer to avoid delaying the core hashtable work. :) |
Signed-off-by: Rain Valentine <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@ranshid The zslGetRank changes have been removed, so I guess it's safe to merge. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small comment which I think we could skip handling for now and maybe only extend the comment.
I did not rescan the entire change so LGTM
if ((node->backward == NULL || node->backward->score < newscore) && | ||
(node->level[0].forward == NULL || node->level[0].forward->score > newscore)) { | ||
node->score = newscore; | ||
return NULL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small mark: it is still possible that a node position change will NOT take place after this check. For example in case we update the score to something that exactly matches the score of the prev or next node.
The check can be extended to check also equality of the score (but will also need to compare the key order).
I guess this is fine for now, but maybe extend the comment above to explain that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the edge cases. Now, we remove and re-insert the node at the same position in this case, which is OK. It's not introduced in this PR anyway. We can convert the comment to a follow-up issue.
We could use zslCompareNodes here, but then we'd need to set the new score before we compare and then revert it if the check fails. Or use a stack-allocated temporary node for comparing, just to be able to use zslCompareNodes.
if ((node->backward == NULL || node->backward->score < newscore) && | |
(node->level[0].forward == NULL || node->level[0].forward->score > newscore)) { | |
node->score = newscore; | |
return NULL; | |
} | |
double oldscore = node->score; | |
node->score = newscore; | |
if ((node->backward == NULL || zslCompareNodes(node->backward, node) <= 0) && | |
zslCompareNodes(node->level[0].forward, node) >= 0) { | |
return NULL; | |
} else { | |
/* Restore score to restore skiplist order. */ | |
node->score = oldscore; | |
} |
about edge cases: allowing score to be equal to pref or next node and also compare ele in these cases. Signed-off-by: Viktor Söderqvist <[email protected]>
This PR replaces dict with hashtable in the ZSET datatype. Instead of mapping key to score as dict did, the hashtable maps key to a node in the skiplist, which contains the score. This takes advantage of hashtable performance improvements and saves 15 bytes per set item - 24 bytes overhead before, 9 bytes after.
Closes #1096