-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Fix HashStringAllocator::clear() and cumulativeBytes_ #10260
Conversation
✅ Deploy Preview for meta-velox canceled.
|
16f6ff9
to
3eaa100
Compare
0e426e0
to
34b7f9e
Compare
Hi @xiaoxmeng can you please help review this? Thanks! |
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.
@wypb thanks!
@@ -305,7 +305,8 @@ class HashStringAllocator : public StreamArena { | |||
/// the pointer because in the worst case we would have one allocation that | |||
/// chains many small free blocks together via kContinued. | |||
uint64_t freeSpace() const { | |||
int64_t minFree = freeBytes_ - numFree_ * (sizeof(Header) + sizeof(void*)); | |||
int64_t minFree = |
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.
const int64_t minFree
@@ -433,8 +470,8 @@ void HashStringAllocator::free(Header* header) { | |||
freeToPool(headerToFree, headerToFree->size() + sizeof(Header)); | |||
} else { | |||
VELOX_CHECK(!headerToFree->isFree()); | |||
freeBytes_ += headerToFree->size() + sizeof(Header); | |||
cumulativeBytes_ -= headerToFree->size(); | |||
freeBytes_ += headerToFree->size() + kHeaderSize; |
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 add a anonymous function say
inline size_t blockBytes(blockHeader) {
return blockHeader->size() + kHeaderSize;
}
@@ -697,15 +734,15 @@ int64_t HashStringAllocator::checkConsistency() const { | |||
*(reinterpret_cast<int32_t*>(header->end()) - 1)); | |||
} | |||
++numFree; | |||
freeBytes += sizeof(Header) + header->size(); | |||
freeBytes += kHeaderSize + header->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.
ditto
} else if (header->isContinued()) { | ||
// If the content of the header is continued, check the continued | ||
// header is readable and not free. | ||
auto* continued = header->nextContinued(); | ||
VELOX_CHECK(!continued->isFree()); | ||
allocatedBytes += header->size() - sizeof(void*); | ||
allocatedBytes += header->size() + kHeaderSize; |
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.
ditto
|
||
static const auto kHugePageSize = memory::AllocationTraits::kHugePageSize; | ||
for (auto i = 0; i < pool_.numRanges(); ++i) { | ||
auto topRange = pool_.rangeAt(i); |
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.
const auto topRange = pool_.rangeAt(i);
const auto topRangeSize = topRange.size();
std::min<int64_t>(topRangeSize, kHugePageSize)); | ||
const auto size = range.size() - simd::kPadding; | ||
auto* end = reinterpret_cast<Header*>(range.data() + size); | ||
auto* header = reinterpret_cast<Header*>(range.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.
Can we have define macro for this?
#define HEADER(ptr) reinterpret_cast<Header*>(ptr)
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.
Because Velox does not recommend using macros, so I created a new static Header* castToHeader(const void* data)
method.
587fd5d
to
15ed556
Compare
Hi @xiaoxmeng I have refactored the code based on the review comments. please help me review it again when you have a chance. Thanks! |
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.
@wypb LGTM. Thanks for helping on this!
@@ -83,6 +83,10 @@ std::string HashStringAllocator::Header::toString() { | |||
|
|||
HashStringAllocator::~HashStringAllocator() { | |||
clear(); | |||
#ifdef NDEBUG | |||
VELOX_CHECK_EQ(state_.cumulativeBytes(), 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.
You can use VELOX_DCHECK_EQ here?
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 you move these two checks in clear()?
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've moved it in clear() as suggested. Thanks.
#ifdef NDEBUG | ||
static const auto kHugePageSize = memory::AllocationTraits::kHugePageSize; | ||
for (auto i = 0; i < state_.pool().numRanges(); ++i) { | ||
const auto topRange = state_.pool().rangeAt(i); |
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.
const auto range = state_.pool().rangeAt(i);
const auto rangeSize = topRange.size();
VELOX_CHECK_EQ(0, topRangeSize % kHugePageSize); | ||
} | ||
|
||
for (int64_t subRangeStart = 0; subRangeStart < topRangeSize; |
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.
s/subRangeStart/blockOffset/
reinterpret_cast<char*>(header->end()), | ||
reinterpret_cast<char*>(end)); | ||
|
||
if (header->isFree()) { |
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 (!header->isFree()) {
...
}
|
||
for (int64_t subRangeStart = 0; subRangeStart < topRangeSize; | ||
subRangeStart += kHugePageSize) { | ||
auto range = folly::Range<char*>( |
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.
s/range/blockRange/
@xiaoxmeng has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@wypb thanks and left few more nits. Thanks! |
55ee1c2
to
13106b4
Compare
ab38741
to
6d2b30e
Compare
@xiaoxmeng has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@xiaoxmeng merged this pull request in c54e59d. |
Conbench analyzed the 1 benchmark run on commit There were no benchmark performance regressions. 🎉 The full Conbench report has more details. |
Summary: This PR solves the following issues:
cumulativeBytes_
is the counter of allocated bytes, if we allocate n blocks and then execute free() on these blocks, the final value ofcumulativeBytes_
should be equal to 0. But without this PR, the value ofcumulativeBytes_
is not equal to 0. seeHashStringAllocatorTest#multipleFreeAncCheckCumulativeBytes
test case in this PR. This is because we don't include the size of theHeader
when calculating the allocated bytes.HashStringAllocator::clear()
, we need to decrement memory counters. PR Fix HashStringAllocator::clear #10053 only decrement memory counters when releasingallocationsFromPool_
. We also need to decrement the memory counters when releasing memory requested bymemory::AllocationPool
.HashStringAllocator::clear()
, the values ofcumulativeBytes_
andsizeFromPool_
should be equal to 0.CC: @xiaoxmeng @mbasmanova