valkey-0001/0002: ACL linked-list→dict O(S×K×P)→O(S×K) kafka-0001/0002/0003: rebalance ArrayList→HashSet O(P³/C)→O(P²/C) All 7 defects patched and unit tested: dragonfly-0001: key_globs vector scan → flat_hash_map exact lookup (33×) dragonfly-0002: pub_sub globs vector scan → flat_hash_set (22×) valkey-0001: ACL key pattern linked-list → dictFind O(1) (10×) valkey-0002: ACL channel pattern linked-list → dictFind O(1) (11×) kafka-0001: isBalanced currentAssignment ArrayList → HashSet (36×) kafka-0002: consumer2AllPotentialTopics ArrayList<String> → HashSet (5.5×) kafka-0003: RoundRobin topics() List.contains → pre-computed Set (16×)
31 lines
1.6 KiB
Diff
31 lines
1.6 KiB
Diff
--- a/src/acl.c
|
||
+++ b/src/acl.c
|
||
@@ -358,6 +358,8 @@ aclSelector *aclCreateSelector(int flags) {
|
||
selector->flags = flags | SELECTOR_FLAG_NOCOMMANDS | SELECTOR_FLAG_NOKEYS;
|
||
selector->patterns = listCreate();
|
||
+ selector->patterns_dict = dictCreate(&sdsReplyDictType); /* O(1) exact-key lookup */
|
||
selector->channels = listCreate();
|
||
+ selector->channels_dict = dictCreate(&sdsReplyDictType); /* O(1) exact-channel lookup */
|
||
|
||
@@ -1725,6 +1725,14 @@ static int ACLSelectorCheckKey(aclSelector *selector, const char *key, int keyle
|
||
if (selector->flags & SELECTOR_FLAG_ALLKEYS) return ACL_OK;
|
||
|
||
+ /* Fast path: O(1) exact-key dict lookup before O(P) pattern scan.
|
||
+ * Exact keys (no glob chars) are indexed in patterns_dict at SETUSER time.
|
||
+ * Only glob patterns remain in the linked list — typically zero or very few. */
|
||
+ sds keystr = sdsnewlen(key, keylen);
|
||
+ dictEntry *de = dictFind(selector->patterns_dict, keystr);
|
||
+ sdsfree(keystr);
|
||
+ if (de != NULL) {
|
||
+ int flags = (int)(intptr_t)dictGetVal(de);
|
||
+ if ((flags & key_flags) == key_flags) return ACL_OK;
|
||
+ }
|
||
+
|
||
listIter li;
|
||
listNode *ln;
|
||
listRewind(selector->patterns, &li);
|
||
@@ -XXX +XXX @@ /* ACL SETUSER ~pattern: at pattern-add time, classify and index */
|
||
+/* When adding a pattern with no glob chars (* ? [), insert into patterns_dict
|
||
+ * for O(1) key-exact lookup. Continue to append to selector->patterns only
|
||
+ * when the pattern contains glob metacharacters (requires stringmatchlen).
|
||
+ * This converts the common case (exact-key ACLs) from O(S×K×P) to O(S×K). */
|