-
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?
Changes from all commits
8cd8de0
03e1af3
2bc801d
ac3cf7c
33a2c2c
919a6df
df95793
b9d2033
4843b19
2340315
ec5917e
7820d21
6423c13
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,8 +13,11 @@ | |
#include "HttpReply.h" | ||
#include "mem_node.h" | ||
#include "MemObject.h" | ||
#include "SquidMath.h" | ||
#include "stmem.h" | ||
|
||
size_t mem_hdr::ReplPolicyIdleNodesCount = 0; | ||
|
||
/* | ||
* NodeGet() is called to get the data buffer to pass to storeIOWrite(). | ||
* By setting the write_pending flag here we are assuming that there | ||
|
@@ -58,7 +61,9 @@ mem_hdr::endOffset () const | |
void | ||
mem_hdr::freeContent() | ||
{ | ||
const auto initialNodes = size(); | ||
nodes.destroy(); | ||
updateIdleNodes(initialNodes); | ||
inmem_hi = 0; | ||
debugs(19, 9, this << " hi: " << inmem_hi); | ||
} | ||
|
@@ -72,8 +77,10 @@ mem_hdr::unlink(mem_node *aNode) | |
} | ||
|
||
debugs(19, 8, this << " removing " << aNode); | ||
const auto initialNodes = size(); | ||
nodes.remove (aNode, NodeCompare); | ||
delete aNode; | ||
updateIdleNodes(initialNodes); | ||
return true; | ||
} | ||
|
||
|
@@ -320,18 +327,20 @@ mem_hdr::write (StoreIOBuffer const &writeBuffer) | |
char *currentSource = writeBuffer.data; | ||
size_t len = writeBuffer.length; | ||
|
||
const auto initialNodes = size(); | ||
while (len && (target = nodeToRecieve(currentOffset))) { | ||
size_t wrote = writeAvailable(target, currentOffset, len, currentSource); | ||
assert (wrote); | ||
len -= wrote; | ||
currentOffset += wrote; | ||
currentSource += wrote; | ||
} | ||
updateIdleNodes(initialNodes); | ||
|
||
return true; | ||
} | ||
|
||
mem_hdr::mem_hdr() : inmem_hi(0) | ||
mem_hdr::mem_hdr() : inmem_hi(0), removableByReplPolicy(false) | ||
{ | ||
debugs(19, 9, this << " hi: " << inmem_hi); | ||
} | ||
|
@@ -376,3 +385,40 @@ mem_hdr::getNodes() const | |
return nodes; | ||
} | ||
|
||
static void | ||
UpdateIdleNodesCounter(const size_t oldSize, const size_t newSize) | ||
{ | ||
if (newSize == oldSize) | ||
return; | ||
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(); | ||
} else { | ||
assert(mem_hdr::ReplPolicyIdleNodesCount >= delta); | ||
mem_hdr::ReplPolicyIdleNodesCount -= delta; | ||
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.
Agreed. We are essentially asserting that there is no underflow, and I missed that fact. |
||
} | ||
rousskov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
debugs(19, 5, "Updated ReplPolicyIdleNodesCount from " << oldCount << " to " << mem_hdr::ReplPolicyIdleNodesCount); | ||
} | ||
|
||
void | ||
mem_hdr::allowedToFreeWithReplPolicy(const bool allowed) | ||
{ | ||
if (removableByReplPolicy == allowed) | ||
return; | ||
removableByReplPolicy = allowed; | ||
const auto oldSize = removableByReplPolicy ? 0 : size(); | ||
const auto newSize = removableByReplPolicy ? size() : 0; | ||
UpdateIdleNodesCounter(oldSize, newSize); | ||
} | ||
|
||
/// Adjusts the ReplPolicyIdleNodesCount counter by the difference | ||
/// between the current size() and oldSize. | ||
void | ||
mem_hdr::updateIdleNodes(const size_t oldSize) | ||
{ | ||
if (!removableByReplPolicy) | ||
return; | ||
UpdateIdleNodesCounter(oldSize, size()); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -419,6 +419,8 @@ void | |
StoreEntry::lock(const char *context) | ||
{ | ||
++lock_count; | ||
if (mem_obj) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(false); | ||
debugs(20, 3, context << " locked key " << getMD5Text() << ' ' << *this); | ||
} | ||
|
||
|
@@ -450,6 +452,9 @@ StoreEntry::unlock(const char *context) | |
if (lock_count) | ||
return (int) lock_count; | ||
|
||
if (mem_obj) | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(mem_obj->repl.data); | ||
|
||
abandon(context); | ||
return 0; | ||
} | ||
|
@@ -756,6 +761,7 @@ 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 commentThe 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 commentThe 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(). |
||
assert(locked()); | ||
|
||
// XXX: caller uses content offset, but we also store headers | ||
writeBuffer.offset += mem_obj->baseReply().hdr_sz; | ||
|
@@ -1513,13 +1519,16 @@ StoreEntry::setMemStatus(mem_status_t new_status) | |
} else { | ||
mem_policy->Add(mem_policy, this, &mem_obj->repl); | ||
debugs(20, 4, "inserted " << *this << " key: " << getMD5Text()); | ||
// only idle entries can be freed by the replacement policy | ||
mem_obj->data_hdr.allowedToFreeWithReplPolicy(!locked()); | ||
} | ||
|
||
++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_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 commentThe reason will be displayed to describe this comment to others. Learn more.
Why? I assume that if this (used to be 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 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.
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. |
||
debugs(20, 4, "removed " << *this); | ||
} | ||
|
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.
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?