-
Notifications
You must be signed in to change notification settings - Fork 3
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
Optimize freeMemorySpace() to not loop in vain #200
base: master
Are you sure you want to change the base?
Optimize freeMemorySpace() to not loop in vain #200
Conversation
We should not perform this loop if the total number of idle memory pages is less than required number of pages.
Also update the global idle page counter when the number of entry's pages changes. Fortunately, there were only few mem_hdr methods (responsible for adding/removing memory nodes) to be adjusted. Also removed a couple of unused mem_hdr methods.
Also properly initialize mem_hdr::isIdle in constructor instead of supplying the correct value later. Also added more invariants (as assertions).
Also adjusted documentation.
We need to minimize the chance of calling mem_hdr::write() directly, i.e., bypassing updating mem_hdr::IdleNodes counter. The only caller now is StoreEntry::writeData(). Ideally, mem_hdr::write() should update IdleNodes itself, but but that would require passing StoreEntry pointer there (to check required conditions), which does not look as a good design. Also fixed test-suite tests.
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 promising, thank you, but more work is needed before we can commit to this solution.
src/Store.h
Outdated
@@ -319,6 +327,9 @@ class StoreEntry : public hash_link, public Packable | |||
/// flags [truncated or too big] entry with ENTRY_BAD_LENGTH and releases it | |||
void lengthWentBad(const char *reason); | |||
|
|||
/// whether methods such as lock()/unlock() also require mem_hdr::IdleNodes counter updating | |||
bool needsIdlePagesUpdating() const { return !lock_count && mem_obj && !EBIT_TEST(flags, ENTRY_SPECIAL); } |
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 method implementation looks simple, but its hidden preconditions and/or implications are actually rather complex! This method cannot be correctly used/interpreted except in some very specific code places -- move its call a few lines up or down, and it will fail to work.
The method also exposes a potential terminology problem: Either we should not be checking ENTRY_SPECIAL (because ENTRY_SPECIAL is never idle) OR we are not really counting idle pages (i.e. we are counting "purge-able" pages).
For now, I suggest just inlining this method calls (and adjusting a bit to remove checks that are not necessary in each particular context). If, at the end of this PR, we still see reusable code that is more-or-less safe to call from various places, we will find a way to encapsulate it again.
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.
I removed this method.
src/store.cc
Outdated
@@ -1543,7 +1561,7 @@ void | |||
StoreEntry::createMemObject() | |||
{ | |||
assert(!mem_obj); | |||
mem_obj = new MemObject(); | |||
mem_obj = new MemObject(locked()); |
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.
Feels wrong that we do not care about ENTRY_SPECIAL here. If (current or future) code reaches this place with an unlocked ENTRY_SPECIAL, we will count "idle" pages we should not count... I hope we can refactor this PR to avoid this problem, but, for now, let's just add an XXX:
mem_obj = new MemObject(locked()); | |
mem_obj = new MemObject(locked()); // XXX: May be unlocked ENTRY_SPECIAL |
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.
I removed this constructor argument. After modifying the condition used for making pages idle (i.e., it should be in a policy) I added an assertion into the MemObject constructor.
src/stmem.cc
Outdated
void | ||
mem_hdr::setIdleness(const bool idle) | ||
{ | ||
assert(idle != isIdle); |
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.
If this code survives, I suggest relaxing it -- doing nothing when idleness does not change. It may even simplify some callers!
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.
Removed this assertion.
src/store.cc
Outdated
const auto oldSize = dataHdr.size(); | ||
assert(dataHdr.write(writeBuffer)); | ||
if (needsIdlePagesUpdating()) | ||
dataHdr.updateIdleNodes(oldSize); |
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 do we need to call this explicitly here? In other words, why cannot dataHdr.write() adjust the idle page counter as needed? Do we not trust its isIdle state??
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.
Removed this call.
These are unlocked pages that can be purged by the removal policy, i.e., by RemovalPurgeWalker.
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.
Done at 2340315.
src/store.cc
Outdated
const auto oldSize = dataHdr.size(); | ||
assert(dataHdr.write(writeBuffer)); | ||
if (needsIdlePagesUpdating()) | ||
dataHdr.updateIdleNodes(oldSize); |
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.
Removed this call.
src/store.cc
Outdated
@@ -1543,7 +1561,7 @@ void | |||
StoreEntry::createMemObject() | |||
{ | |||
assert(!mem_obj); | |||
mem_obj = new MemObject(); | |||
mem_obj = new MemObject(locked()); |
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.
I removed this constructor argument. After modifying the condition used for making pages idle (i.e., it should be in a policy) I added an assertion into the MemObject constructor.
src/stmem.cc
Outdated
void | ||
mem_hdr::setIdleness(const bool idle) | ||
{ | ||
assert(idle != isIdle); |
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.
Removed this assertion.
src/Store.h
Outdated
@@ -319,6 +327,9 @@ class StoreEntry : public hash_link, public Packable | |||
/// flags [truncated or too big] entry with ENTRY_BAD_LENGTH and releases it | |||
void lengthWentBad(const char *reason); | |||
|
|||
/// whether methods such as lock()/unlock() also require mem_hdr::IdleNodes counter updating | |||
bool needsIdlePagesUpdating() const { return !lock_count && mem_obj && !EBIT_TEST(flags, ENTRY_SPECIAL); } |
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.
I removed this method.
src/Store.h
Outdated
@@ -67,6 +72,9 @@ class StoreEntry : public hash_link, public Packable | |||
bool isAccepting() const; | |||
size_t bytesWanted(Range<size_t> const aRange, bool ignoreDelayPool = false) const; | |||
|
|||
/// whether a non-completed (STORE_PENDING) entry is being written to the local memory store | |||
bool isLocalWriter() const { return locked() && isAccepting(); } |
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.
AFAICT, the implementation of this new method does not match its name/description. Even without collapsed forwarding going on, a locked() isAccepting() entry may be "being written" by another worker, right? Locked() is true for virtually every entry "in use" by a worker, and isAccepting() is roughly equivalent to STORE_PENDING, which is true for entries written by any worker IIRC.
This does not necessarily mean the old code using this method condition was wrong -- that condition evaluation could have been placed in the right context, making it correct. I did not check.
The method also appears to rely on a very dangerous assumption that it is only called for STORE_PENDING entries. I think that is a method description defect though -- isLocked() checks STORE_PENDING rather than assuming that the method was called for STORE_PENDING entries.
Please remove this used-twice method. If the above notes did not change your opinion on the condition applicability in the new code, then, in the new caller context, just add an extra assert() or Assure() for locked(). It will also help distinguish the failing condition if the new assertion is triggered.
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.
entry may be "being written" by another worker, right?
Right (i.e. ,written to a shared store), but then copied to by another worker and then written to a local store. In this sense, any STORE_PENDING is probably a 'local writer' and it looks 'too broad' definition. I removed this method.
src/stmem.cc
Outdated
if (newSize == oldSize) | ||
return; |
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.
Nitpick: Please move these two lines up -- we do not need delta
for this special noise-reduction(?) case.
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.
Ok.
src/stmem.cc
Outdated
return; | ||
const auto oldCount = ReplPolicyIdleNodesCount; | ||
if (newSize > oldSize) { | ||
ReplPolicyIdleNodesCount += delta; |
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.
Missing overflow protection. Please use one of the SquidMath.h "natural" functions to protect.
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.
Ok, but is there a possibility that the total number of pages (to say noting of idle pages) can exceed size_t maximum value?
src/stmem.cc
Outdated
ReplPolicyIdleNodesCount += delta; | ||
} else { | ||
assert(ReplPolicyIdleNodesCount >= delta); | ||
ReplPolicyIdleNodesCount -= delta; |
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.
Missing underflow protection. Please use one of the SquidMath.h "natural" functions to protect, adding one if necessary.
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.
I am not sure that 'underflow' is applicable here. How can it happen? We checked that A >= B where both operands are size_t (an unsigned integer type) and then calculate A-B - we must get a size_t C >=0.
src/stmem.cc
Outdated
ReplPolicyIdleNodesCount += size(); | ||
else { | ||
assert(ReplPolicyIdleNodesCount >= size()); | ||
ReplPolicyIdleNodesCount -= size(); |
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.
If possible, please reuse or merge with updateIdleNodes(). Refactor that method a little to be more reusable, as needed (e.g., giving it a second/newSize parameter?).
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.
I was thinking to call one from another - but preconditions in these two methods a different - updateIdleNodes() is called only for idle nodes). I introduced a static helper method to avoid duplication.
src/store.cc
Outdated
} | ||
|
||
++hot_obj_count; // TODO: maintain for the shared hot cache as well | ||
} else { | ||
if (EBIT_TEST(flags, ENTRY_SPECIAL)) { | ||
debugs(20, 4, "not removing special " << *this << " from policy"); | ||
} else { | ||
mem_policy->Remove(mem_policy, this, &mem_obj->repl); | ||
debugs(20, 4, "removed " << *this); | ||
if (hasReplPolicy()) { |
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.
I think we should drop this new condition and the corresponding new method: If we need to assert() that ENTRY_SPECIAL entries are not counted/tracked, we should do that explicitly somewhere (not here where we explicitly check for ENTRY_SPECIAL and mem_obj) rather than implicitly (and rather unexpectedly and dangerously!) in all hasReplPolicy() callers.
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.
Ok, I dropped the method but I think we need a condition (at least for data_hdr.allowedToFreeWithReplPolicy() call): we should skip this call when entry is not in memory policy. On the other hand, mem_policy->Remove() can be called twice - it has a such a check inside.
src/store/Controller.cc
Outdated
@@ -534,6 +534,9 @@ Store::Controller::freeMemorySpace(const int bytesRequired) | |||
if (memoryCacheHasSpaceFor(pagesRequired)) | |||
return; | |||
|
|||
if (mem_hdr::ReplPolicyIdleNodesCount < static_cast<size_t>(pagesRequired)) |
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.
Please use Less() for this comparison to avoid casting and clarify what is going on here:
if (mem_hdr::ReplPolicyIdleNodesCount < static_cast<size_t>(pagesRequired)) | |
// do not free anything if freeing everything freeable would not be enough | |
if (Less(mem_hdr::ReplPolicyIdleNodesCount, pagesRequired)) |
Also safe numeric operations with Less() and IncreaseSum().
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.
Done at 7820d21.
src/Store.h
Outdated
@@ -67,6 +72,9 @@ class StoreEntry : public hash_link, public Packable | |||
bool isAccepting() const; | |||
size_t bytesWanted(Range<size_t> const aRange, bool ignoreDelayPool = false) const; | |||
|
|||
/// whether a non-completed (STORE_PENDING) entry is being written to the local memory store | |||
bool isLocalWriter() const { return locked() && isAccepting(); } |
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.
entry may be "being written" by another worker, right?
Right (i.e. ,written to a shared store), but then copied to by another worker and then written to a local store. In this sense, any STORE_PENDING is probably a 'local writer' and it looks 'too broad' definition. I removed this method.
src/stmem.cc
Outdated
ReplPolicyIdleNodesCount += size(); | ||
else { | ||
assert(ReplPolicyIdleNodesCount >= size()); | ||
ReplPolicyIdleNodesCount -= size(); |
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.
I was thinking to call one from another - but preconditions in these two methods a different - updateIdleNodes() is called only for idle nodes). I introduced a static helper method to avoid duplication.
src/stmem.cc
Outdated
if (newSize == oldSize) | ||
return; |
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.
Ok.
src/stmem.cc
Outdated
return; | ||
const auto oldCount = ReplPolicyIdleNodesCount; | ||
if (newSize > oldSize) { | ||
ReplPolicyIdleNodesCount += delta; |
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.
Ok, but is there a possibility that the total number of pages (to say noting of idle pages) can exceed size_t maximum value?
src/stmem.cc
Outdated
ReplPolicyIdleNodesCount += delta; | ||
} else { | ||
assert(ReplPolicyIdleNodesCount >= delta); | ||
ReplPolicyIdleNodesCount -= delta; |
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.
I am not sure that 'underflow' is applicable here. How can it happen? We checked that A >= B where both operands are size_t (an unsigned integer type) and then calculate A-B - we must get a size_t C >=0.
src/store.cc
Outdated
} | ||
|
||
++hot_obj_count; // TODO: maintain for the shared hot cache as well | ||
} else { | ||
if (EBIT_TEST(flags, ENTRY_SPECIAL)) { | ||
debugs(20, 4, "not removing special " << *this << " from policy"); | ||
} else { | ||
mem_policy->Remove(mem_policy, this, &mem_obj->repl); | ||
debugs(20, 4, "removed " << *this); | ||
if (hasReplPolicy()) { |
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.
Ok, I dropped the method but I think we need a condition (at least for data_hdr.allowedToFreeWithReplPolicy() call): we should skip this call when entry is not in memory policy. On the other hand, mem_policy->Remove() can be called twice - it has a such a check inside.
const auto delta = newSize > oldSize ? newSize - oldSize : oldSize - newSize; | ||
const auto oldCount = mem_hdr::ReplPolicyIdleNodesCount; | ||
if (newSize > oldSize) { | ||
mem_hdr::ReplPolicyIdleNodesCount = IncreaseSum(mem_hdr::ReplPolicyIdleNodesCount, delta).value(); |
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.
is there a possibility that the total number of pages (to say noting of idle pages) can exceed size_t maximum value?
IMO, yes: Buggy code (elsewhere) may forget to decrease the total (in some cases) or may increase the total by more than the number of pages in mem_hdr.
We could assert that there are no overflows, but that requires approximately the same effort AFAICT.
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.
Did the IncreaseSum() address your concern?
mem_hdr::ReplPolicyIdleNodesCount = IncreaseSum(mem_hdr::ReplPolicyIdleNodesCount, delta).value(); | ||
} else { | ||
assert(mem_hdr::ReplPolicyIdleNodesCount >= delta); | ||
mem_hdr::ReplPolicyIdleNodesCount -= delta; |
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.
I am not sure that 'underflow' is applicable here. How can it happen? We checked that A >= B where both operands are size_t (an unsigned integer type) and then calculate A-B - we must get a size_t C >=0.
Agreed. We are essentially asserting that there is no underflow, and I missed that fact.
} | ||
|
||
++hot_obj_count; // TODO: maintain for the shared hot cache as well | ||
} else { | ||
if (EBIT_TEST(flags, ENTRY_SPECIAL)) { | ||
debugs(20, 4, "not removing special " << *this << " from policy"); | ||
} else { | ||
if (mem_obj->repl.data) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(false); | ||
mem_policy->Remove(mem_policy, this, &mem_obj->repl); |
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.
I think we need a condition (at least for data_hdr.allowedToFreeWithReplPolicy() call): we should skip this call when entry is not in memory policy.
Why?
I assume that if this (used to be IN_MEMORY
!) entry is not in mem_policy for some reason, then its removableByReplPolicy flag is already false and calling allowedToFreeWithReplPolicy(false) is harmless. In all other cases, that call will (also) do what it is supposed to do -- decrease the total counter because we are removing the entry from the replacement policy. What am I missing?
In other words, this particular "removal from policy" event alone is sufficient to make removableByReplPolicy false, and our code should express that idea. It is also good to show asymmetry with the true
case above it: It takes several events to make removableByReplPolicy true but only one event to make it false.
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?
The intention was that if we do something with policy, we need to check that the policy exists (i.e., is configured). However you are right that we can call this allowedToFreeWithReplPolicy() even if the policy has been never configured - it will do nothing in this case.
src/store.cc
Outdated
if (!locked()) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); |
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.
I suggest using allowedToFreeWithReplPolicy() "OK to call twice with the same value" convenience/safety feature and avoiding questions about the else
case:
if (!locked()) | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); | |
// only idle entries can be freed by the replacement policy | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(!locked()); |
Alternatively, we should document what is going on in that (somewhat expected or should-be-common) else
case:
if (!locked()) | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); | |
if (!locked()) | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); | |
// else the replacement policy cannot free a locked entry |
I prefer the simplicity and clarity of the first variant, despite the extra function calls it causes. If those extra function calls are a concern, we should refactor allowedToFreeWithReplPolicy() declaration/implementation a little, to allow the compiler to inline the no-changes check into callers.
I applied the same logic in another allowedToFreeWithReplPolicy(true) change request, without an explanation.
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.
I applied the first suggestion.
src/store.cc
Outdated
@@ -1949,6 +1968,13 @@ StoreEntry::checkDisk() const | |||
} | |||
} | |||
|
|||
/// whether the entry was added to a memory replacement policy | |||
bool | |||
StoreEntry::hasReplPolicy() const |
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.
Remove as unused?
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.
Removed.
src/store.cc
Outdated
StoreEntry::writeData(StoreIOBuffer writeBuffer) | ||
{ | ||
assert(mem_obj); | ||
debugs(20, 6, "offset " << writeBuffer.offset << " len " << writeBuffer.length); |
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.
If this method survives, to simplify, reduce maintenance costs, and provide more info:
debugs(20, 6, "offset " << writeBuffer.offset << " len " << writeBuffer.length); | |
debugs(20, 6, writeBuffer); |
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.
I removed writeData() method.
src/store.cc
Outdated
assert(mem_obj); | ||
debugs(20, 6, "offset " << writeBuffer.offset << " len " << writeBuffer.length); | ||
auto &dataHdr = mem_obj->data_hdr; | ||
assert (dataHdr.endOffset() || writeBuffer.offset == 0); |
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 is a new assertion (i.e. official code does not check this), right? It seems misplaced because it checks data_hdr-specific logic. Should not it go inside the mem_hdr::write() method instead? It is also rather weak and awkwardly phrased. I wonder whether this PR is the right place to add this assertion... In fact, should this PR add this method at all?? I suspect this method is no longer needed in this PR. If so, please remove instead of polishing.
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 assertion was moved here from (removed) MemObject::write()). After our recent changes, I decided to remove writeData() at all and restore MemObject::write(). If we decide to refactor/eliminate the number off these write() methods scattered across several objects, let's do it separately.
src/store.cc
Outdated
if (!lock_count && mem_obj && mem_obj->repl.data) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(false); |
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.
Let's simplify/streamline this as well:
if (!lock_count && mem_obj && mem_obj->repl.data) | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(false); | |
if (mem_obj) | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(false); |
Please also move this code right after the lock is incremented, to clarify the intent/precondition/cause.
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.
Ok.
src/store.cc
Outdated
if (mem_obj && mem_obj->repl.data) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); |
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.
if (mem_obj && mem_obj->repl.data) | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); | |
if (mem_obj) | |
mem_obj->data_hdr.allowedToFreeWithReplPolicy(mem_obj->repl.data); |
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.
Ok.
@@ -755,14 +760,14 @@ StoreEntry::write (StoreIOBuffer writeBuffer) | |||
{ | |||
assert(mem_obj != nullptr); | |||
/* This assert will change when we teach the store to update */ | |||
assert(store_status == STORE_PENDING); |
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.
Can we keep this assertion? It feels like it was correct or, at the very least, should not be removed in this PR.
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.
Restored: this was first moved to isLocalWriter(), but then I forgot to undo after removing isLocalWriter().
Also restored MemObject::write() and undone other write()-related refactoring.
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.
Done with this iteration at 6423c13.
const auto delta = newSize > oldSize ? newSize - oldSize : oldSize - newSize; | ||
const auto oldCount = mem_hdr::ReplPolicyIdleNodesCount; | ||
if (newSize > oldSize) { | ||
mem_hdr::ReplPolicyIdleNodesCount = IncreaseSum(mem_hdr::ReplPolicyIdleNodesCount, delta).value(); |
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.
Did the IncreaseSum() address your concern?
src/store.cc
Outdated
if (!lock_count && mem_obj && mem_obj->repl.data) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(false); |
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.
Ok.
src/store.cc
Outdated
if (mem_obj && mem_obj->repl.data) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); |
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.
Ok.
@@ -755,14 +760,14 @@ StoreEntry::write (StoreIOBuffer writeBuffer) | |||
{ | |||
assert(mem_obj != nullptr); | |||
/* This assert will change when we teach the store to update */ | |||
assert(store_status == STORE_PENDING); |
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.
Restored: this was first moved to isLocalWriter(), but then I forgot to undo after removing isLocalWriter().
src/store.cc
Outdated
if (!locked()) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(true); |
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.
I applied the first suggestion.
src/store.cc
Outdated
@@ -1557,7 +1576,7 @@ void | |||
StoreEntry::ensureMemObject(const char *aUrl, const char *aLogUrl, const HttpRequestMethod &aMethod) | |||
{ | |||
if (!mem_obj) | |||
mem_obj = new MemObject(); | |||
createMemObject(); |
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.
Undone.
src/store.cc
Outdated
@@ -1949,6 +1968,13 @@ StoreEntry::checkDisk() const | |||
} | |||
} | |||
|
|||
/// whether the entry was added to a memory replacement policy | |||
bool | |||
StoreEntry::hasReplPolicy() const |
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.
Removed.
src/store.cc
Outdated
assert(mem_obj); | ||
debugs(20, 6, "offset " << writeBuffer.offset << " len " << writeBuffer.length); | ||
auto &dataHdr = mem_obj->data_hdr; | ||
assert (dataHdr.endOffset() || writeBuffer.offset == 0); |
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 assertion was moved here from (removed) MemObject::write()). After our recent changes, I decided to remove writeData() at all and restore MemObject::write(). If we decide to refactor/eliminate the number off these write() methods scattered across several objects, let's do it separately.
src/store.cc
Outdated
debugs(20, 6, "offset " << writeBuffer.offset << " len " << writeBuffer.length); | ||
auto &dataHdr = mem_obj->data_hdr; | ||
assert (dataHdr.endOffset() || writeBuffer.offset == 0); | ||
assert(dataHdr.write(writeBuffer)); |
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.
I removed writeData() method.
src/store.cc
Outdated
StoreEntry::writeData(StoreIOBuffer writeBuffer) | ||
{ | ||
assert(mem_obj); | ||
debugs(20, 6, "offset " << writeBuffer.offset << " len " << writeBuffer.length); |
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.
I removed writeData() method.
We should not perform this loop if the total number of idle memory pages
is less than required number of pages. An idle memory page in this scope
is an unlocked page in the local memory cache, belonging to a
replacement memory policy.