This repository was archived by the owner on Feb 16, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 396
Scale private oh #4364
Merged
+47
−14
Merged
Scale private oh #4364
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,7 +73,8 @@ struct rush { | |
| }; | ||
|
|
||
| static const struct hash_slinger *hash; | ||
| static struct objhead *private_oh; | ||
| #define PRIVATE_OH_EXP 7 | ||
| static struct objhead private_ohs[1 << PRIVATE_OH_EXP]; | ||
|
|
||
| static void hsh_rush1(const struct worker *, struct objhead *, | ||
| struct rush *, int); | ||
|
|
@@ -93,17 +94,23 @@ VCF_RETURNS() | |
|
|
||
| /*---------------------------------------------------------------------*/ | ||
|
|
||
| static struct objhead * | ||
| hsh_newobjhead(void) | ||
| static void | ||
| hsh_initobjhead(struct objhead *oh) | ||
| { | ||
| struct objhead *oh; | ||
|
|
||
| ALLOC_OBJ(oh, OBJHEAD_MAGIC); | ||
| XXXAN(oh); | ||
| INIT_OBJ(oh, OBJHEAD_MAGIC); | ||
| oh->refcnt = 1; | ||
| VTAILQ_INIT(&oh->objcs); | ||
| VTAILQ_INIT(&oh->waitinglist); | ||
| Lck_New(&oh->mtx, lck_objhdr); | ||
| } | ||
|
|
||
| static struct objhead * | ||
| hsh_newobjhead(void) | ||
| { | ||
| struct objhead *oh = malloc(sizeof *oh); | ||
| hsh_initobjhead(oh); | ||
| return (oh); | ||
| } | ||
|
|
||
|
|
@@ -131,22 +138,37 @@ hsh_prealloc(struct worker *wrk) | |
|
|
||
| /*---------------------------------------------------------------------*/ | ||
|
|
||
| // https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/ | ||
| static inline size_t | ||
| fib(uint64_t n, uint8_t bits) | ||
| { | ||
| const uint64_t gr = 11400714819323198485LLU; | ||
| uint64_t r; | ||
|
|
||
| r = n * gr; | ||
| r >>= (sizeof(gr) * 8) - bits; | ||
| assert(r < (size_t)1 << bits); | ||
| return ((size_t)r); | ||
| } | ||
|
Comment on lines
+141
to
+152
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not take the first byte of the request hash? No modulo involved, possibly one
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My main driver is |
||
|
|
||
| struct objcore * | ||
| HSH_Private(const struct worker *wrk) | ||
| { | ||
| struct objcore *oc; | ||
| struct objhead *oh; | ||
|
|
||
| CHECK_OBJ_NOTNULL(private_oh, OBJHEAD_MAGIC); | ||
| oh = &private_ohs[fib((uintptr_t)wrk, PRIVATE_OH_EXP)]; | ||
| CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); | ||
|
|
||
| oc = ObjNew(wrk); | ||
| AN(oc); | ||
| oc->refcnt = 1; | ||
| oc->objhead = private_oh; | ||
| oc->objhead = oh; | ||
| oc->flags |= OC_F_PRIVATE; | ||
| Lck_Lock(&private_oh->mtx); | ||
| VTAILQ_INSERT_TAIL(&private_oh->objcs, oc, hsh_list); | ||
| private_oh->refcnt++; | ||
| Lck_Unlock(&private_oh->mtx); | ||
| Lck_Lock(&oh->mtx); | ||
| VTAILQ_INSERT_TAIL(&oh->objcs, oc, hsh_list); | ||
| oh->refcnt++; | ||
| Lck_Unlock(&oh->mtx); | ||
| return (oc); | ||
| } | ||
|
|
||
|
|
@@ -1108,14 +1130,21 @@ hsh_deref_objhead_unlock(struct worker *wrk, struct objhead **poh, int max) | |
|
|
||
| Lck_AssertHeld(&oh->mtx); | ||
|
|
||
| if (oh == private_oh) { | ||
| if (oh >= private_ohs && oh < private_ohs + vcountof(private_ohs)) { | ||
| assert(VTAILQ_EMPTY(&oh->waitinglist)); | ||
| assert(oh->refcnt > 1); | ||
| oh->refcnt--; | ||
| Lck_Unlock(&oh->mtx); | ||
| return (1); | ||
| } | ||
|
|
||
| //lint --e{661} | ||
| //lint -specific(-e661) | ||
| // | ||
| // because of the static array, flexelint thinks that all ohs were from | ||
| // the static array :( the above suppression applies to the remainder of | ||
| // this function body and specific walks involving this function | ||
|
|
||
| INIT_OBJ(&rush, RUSH_MAGIC); | ||
| if (!VTAILQ_EMPTY(&oh->waitinglist)) { | ||
| assert(oh->refcnt > 1); | ||
|
|
@@ -1151,6 +1180,10 @@ HSH_Init(const struct hash_slinger *slinger) | |
| hash = slinger; | ||
| if (hash->start != NULL) | ||
| hash->start(); | ||
| private_oh = hsh_newobjhead(); | ||
| private_oh->refcnt = 1; | ||
| for (struct objhead *oh = private_ohs; | ||
| oh < private_ohs + vcountof(private_ohs); | ||
| oh++) { | ||
| hsh_initobjhead(oh); | ||
| assert(oh->refcnt == 1); | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Why not define a constant?
I understand the purpose of
vcountof()but if it confuses our tooling, it's maybe not worth using.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.
How does it confuse our tooling?
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 part of the pull request description, before you edited it to strike the second sentence out:
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.
The relevant part is the other bit of the description:
This has nothing to do with
vcountof(), what misleads flexelint is the fact that, with the static array for private objheads, the "others" are on the heap with arbitrary addresses. The reasoning of the tool is here "hey, if there is a check for an upper bound, but then an else branch, that else branch will probably be out of bounds".I think the improved more selective silencing of flexelint is acceptable now.