[Allocator] Drop RedZoneSize (non-sanitizer) and BytesAllocated members (#205711)
`RedZoneSize` is only read inside `#if LLVM_ADDRESS_SANITIZER_BUILD`. Additionally gate it under `LLVM_ENABLE_ABI_BREAKING_CHECKS` so that release-non-assertions builds don't incur the overhead. To support non-asan build with asan library users, the variable is only omitted in `!LLVM_ENABLE_ABI_BREAKING_CHECKS` builds. `BytesAllocated` is incremented on every Allocate (a hot-path memory read-modify-write) only to back `getBytesAllocated()`. Drop the member. There is a measurable stage2 instruction-count reduction. https://llvm-compile-time-tracker.com/compare.php?from=25a6b5be6853b2c493ef392d41e43dd35ad4839a&to=8ebc975635ad717deb392d20b50f1a1f6bb16054&stat=instructions:u Migrate the in-tree consumers: - TableGen dumpAllocationStats drops the line; the clangd debug log reports getTotalMemory(). - clang's PPMemoryAllocationsTest measures getTotalMemory()/#define; over 1M defines this is 120.06 B/define, matching the prior ~120 B, so the existing bound holds. - lldb's ConstString MemoryStats (https://reviews.llvm.org/D117914) drops bytes_used/bytes_unused Aided by Claude Opus 4.8
This commit is contained in:
parent
fc43f7d5d1
commit
ca59c69132
17 changed files with 38 additions and 130 deletions
|
|
@ -560,8 +560,8 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) {
|
|||
dlog(" {0} #={1} *={2} Mode={3}", R.Text, R.ExactArgs, R.PrefixArgs,
|
||||
int(R.Modes));
|
||||
}
|
||||
dlog("Table spellings={0} rules={1} string-bytes={2}", Result->size(),
|
||||
RuleCount, Result->getAllocator().getBytesAllocated());
|
||||
dlog("Table spellings={0} rules={1} allocator-bytes={2}", Result->size(),
|
||||
RuleCount, Result->getAllocator().getTotalMemory());
|
||||
#endif
|
||||
// The static table will never be destroyed.
|
||||
return Result.release();
|
||||
|
|
|
|||
|
|
@ -77,10 +77,13 @@ TEST_F(PPMemoryAllocationsTest, PPMacroDefinesAllocations) {
|
|||
|
||||
PP.LexTokensUntilEOF();
|
||||
|
||||
size_t NumAllocated = PP.getPreprocessorAllocator().getBytesAllocated();
|
||||
float BytesPerDefine = float(NumAllocated) / float(NumMacros);
|
||||
llvm::errs() << "Num preprocessor allocations for " << NumMacros
|
||||
<< " #define: " << NumAllocated << "\n";
|
||||
// Use the total slab memory held by the preprocessor's allocator as a proxy.
|
||||
// Over a million #defines the per-allocation slab overhead is negligible, so
|
||||
// this closely tracks the bytes requested for storing the macro information.
|
||||
size_t TotalMemory = PP.getPreprocessorAllocator().getTotalMemory();
|
||||
float BytesPerDefine = float(TotalMemory) / float(NumMacros);
|
||||
llvm::errs() << "Preprocessor allocator memory for " << NumMacros
|
||||
<< " #define: " << TotalMemory << "\n";
|
||||
llvm::errs() << "Bytes per #define: " << BytesPerDefine << "\n";
|
||||
// On arm64-apple-macos, we get around 120 bytes per define.
|
||||
// Assume a reasonable upper bound based on that number that we don't want
|
||||
|
|
|
|||
|
|
@ -393,10 +393,7 @@ public:
|
|||
|
||||
struct MemoryStats {
|
||||
size_t GetBytesTotal() const { return bytes_total; }
|
||||
size_t GetBytesUsed() const { return bytes_used; }
|
||||
size_t GetBytesUnused() const { return bytes_total - bytes_used; }
|
||||
size_t bytes_total = 0;
|
||||
size_t bytes_used = 0;
|
||||
};
|
||||
|
||||
static MemoryStats GetMemoryStats();
|
||||
|
|
|
|||
|
|
@ -111,8 +111,6 @@ json::Value ModuleStats::ToJSON() const {
|
|||
llvm::json::Value ConstStringStats::ToJSON() const {
|
||||
json::Object obj;
|
||||
obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
|
||||
obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
|
||||
obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,7 +196,6 @@ public:
|
|||
std::shared_lock<PoolMutex> lock(pool.m_mutex);
|
||||
const Allocator &alloc = pool.m_string_map.getAllocator();
|
||||
stats.bytes_total += alloc.getTotalMemory();
|
||||
stats.bytes_used += alloc.getBytesAllocated();
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -348,8 +348,6 @@ class TestCase(TestBase):
|
|||
strings = memory["strings"]
|
||||
strings_keys = [
|
||||
"bytesTotal",
|
||||
"bytesUsed",
|
||||
"bytesUnused",
|
||||
]
|
||||
self.verify_keys(strings, '"strings"', strings_keys, None)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#define LLVM_SUPPORT_ALLOCATOR_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Config/abi-breaking.h"
|
||||
#include "llvm/Support/Alignment.h"
|
||||
#include "llvm/Support/AllocatorBase.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
|
@ -36,9 +37,7 @@ namespace detail {
|
|||
|
||||
// We call out to an external function to actually print the message as the
|
||||
// printing code uses Allocator.h in its implementation.
|
||||
LLVM_ABI void printBumpPtrAllocatorStats(unsigned NumSlabs,
|
||||
size_t BytesAllocated,
|
||||
size_t TotalMemory);
|
||||
LLVM_ABI void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t TotalMemory);
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
|
|
@ -96,11 +95,12 @@ public:
|
|||
BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
|
||||
: AllocTy(std::move(Old.getAllocator())), CurPtr(Old.CurPtr),
|
||||
EndSentinel(Old.EndSentinel), Slabs(std::move(Old.Slabs)),
|
||||
CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
|
||||
BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize) {
|
||||
CustomSizedSlabs(std::move(Old.CustomSizedSlabs)) {
|
||||
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
|
||||
RedZoneSize = Old.RedZoneSize;
|
||||
#endif
|
||||
Old.CurPtr = nullptr;
|
||||
Old.EndSentinel = 0;
|
||||
Old.BytesAllocated = 0;
|
||||
Old.Slabs.clear();
|
||||
Old.CustomSizedSlabs.clear();
|
||||
}
|
||||
|
|
@ -116,15 +116,15 @@ public:
|
|||
|
||||
CurPtr = RHS.CurPtr;
|
||||
EndSentinel = RHS.EndSentinel;
|
||||
BytesAllocated = RHS.BytesAllocated;
|
||||
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
|
||||
RedZoneSize = RHS.RedZoneSize;
|
||||
#endif
|
||||
Slabs = std::move(RHS.Slabs);
|
||||
CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
|
||||
AllocTy::operator=(std::move(RHS.getAllocator()));
|
||||
|
||||
RHS.CurPtr = nullptr;
|
||||
RHS.EndSentinel = 0;
|
||||
RHS.BytesAllocated = 0;
|
||||
RHS.Slabs.clear();
|
||||
RHS.CustomSizedSlabs.clear();
|
||||
return *this;
|
||||
|
|
@ -141,7 +141,6 @@ public:
|
|||
return;
|
||||
|
||||
// Reset the state.
|
||||
BytesAllocated = 0;
|
||||
CurPtr = (char *)Slabs.front();
|
||||
EndSentinel = uintptr_t(CurPtr) + SlabSize + 1;
|
||||
|
||||
|
|
@ -158,12 +157,10 @@ public:
|
|||
// Allocate(0, N) is valid, it returns a non-null pointer (which should not
|
||||
// be dereferenced).
|
||||
LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, Align Alignment) {
|
||||
// Keep track of how many bytes we've allocated.
|
||||
BytesAllocated += Size;
|
||||
|
||||
size_t SizeToAllocate = Size;
|
||||
#if LLVM_ADDRESS_SANITIZER_BUILD
|
||||
// Add trailing bytes as a "red zone" under ASan.
|
||||
#if LLVM_ADDRESS_SANITIZER_BUILD && LLVM_ENABLE_ABI_BREAKING_CHECKS
|
||||
// Add trailing bytes as a "red zone" under ASan. RedZoneSize only exists
|
||||
// when both conditions are true.
|
||||
SizeToAllocate += RedZoneSize;
|
||||
#endif
|
||||
SizeToAllocate = alignToPowerOf2(SizeToAllocate, MinAlign);
|
||||
|
|
@ -308,15 +305,14 @@ public:
|
|||
return TotalMemory;
|
||||
}
|
||||
|
||||
size_t getBytesAllocated() const { return BytesAllocated; }
|
||||
|
||||
void setRedZoneSize(size_t NewSize) {
|
||||
void setRedZoneSize([[maybe_unused]] size_t NewSize) {
|
||||
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
|
||||
RedZoneSize = NewSize;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintStats() const {
|
||||
detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
|
||||
getTotalMemory());
|
||||
detail::printBumpPtrAllocatorStats(Slabs.size(), getTotalMemory());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -335,14 +331,11 @@ private:
|
|||
/// Custom-sized slabs allocated for too-large allocation requests.
|
||||
SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs;
|
||||
|
||||
/// How many bytes we've allocated.
|
||||
///
|
||||
/// Used so that we can compute how much space was wasted.
|
||||
size_t BytesAllocated = 0;
|
||||
|
||||
/// The number of bytes to put between allocations when running under
|
||||
/// a sanitizer.
|
||||
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
|
||||
/// The number of bytes to put between allocations when running under a
|
||||
/// sanitizer.
|
||||
size_t RedZoneSize = 1;
|
||||
#endif
|
||||
|
||||
static size_t computeSlabSize(unsigned SlabIdx) {
|
||||
// Scale the actual allocated slab size based on the number of slabs
|
||||
|
|
@ -472,8 +465,6 @@ public:
|
|||
std::optional<int64_t> identifyObject(const void *Ptr) {
|
||||
return Allocator.identifyObject(Ptr);
|
||||
}
|
||||
|
||||
size_t getBytesAllocated() const { return Allocator.getBytesAllocated(); }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
|||
|
|
@ -82,16 +82,6 @@ public:
|
|||
return TotalMemory;
|
||||
}
|
||||
|
||||
/// Return allocated size by all allocators.
|
||||
size_t getBytesAllocated() const {
|
||||
size_t BytesAllocated = 0;
|
||||
|
||||
for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
|
||||
BytesAllocated += Allocators[Idx].getBytesAllocated();
|
||||
|
||||
return BytesAllocated;
|
||||
}
|
||||
|
||||
/// Set red zone for all allocators.
|
||||
void setRedZoneSize(size_t NewSize) {
|
||||
for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
|
||||
|
|
|
|||
|
|
@ -17,12 +17,9 @@ namespace llvm {
|
|||
|
||||
namespace detail {
|
||||
|
||||
void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
|
||||
size_t TotalMemory) {
|
||||
void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t TotalMemory) {
|
||||
errs() << "\nNumber of memory regions: " << NumSlabs << '\n'
|
||||
<< "Bytes used: " << BytesAllocated << '\n'
|
||||
<< "Bytes allocated: " << TotalMemory << '\n'
|
||||
<< "Bytes wasted: " << (TotalMemory - BytesAllocated)
|
||||
<< " (includes alignment, etc)\n";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ void detail::RecordKeeperImpl::dumpAllocationStats(raw_ostream &OS) const {
|
|||
OS << "TheVarBitInitPool size = " << TheVarBitInitPool.size() << '\n';
|
||||
OS << "TheVarDefInitPool size = " << TheVarDefInitPool.size() << '\n';
|
||||
OS << "TheFieldInitPool size = " << TheFieldInitPool.size() << '\n';
|
||||
OS << "Bytes allocated = " << Allocator.getBytesAllocated() << '\n';
|
||||
OS << "Total allocator memory = " << Allocator.getTotalMemory() << "\n\n";
|
||||
|
||||
OS << "Number of records instantiated = " << LastRecordID << '\n';
|
||||
|
|
|
|||
|
|
@ -368,9 +368,8 @@ const MaterializedConstant *Context::getConstantValue(Constant *C) {
|
|||
if (Val.isNone())
|
||||
return nullptr;
|
||||
if (!Val.isCacheable()) {
|
||||
assert(NoncacheableConstBuffer.getBytesAllocated() <=
|
||||
1024 * sizeof(MaterializedConstant) &&
|
||||
"Unbounded temporary buffer.");
|
||||
assert(NoncacheableConstCount <= 1024 && "Unbounded temporary buffer.");
|
||||
++NoncacheableConstCount;
|
||||
return new (NoncacheableConstBuffer.Allocate())
|
||||
MaterializedConstant(std::move(Val));
|
||||
}
|
||||
|
|
@ -380,6 +379,7 @@ const MaterializedConstant *Context::getConstantValue(Constant *C) {
|
|||
|
||||
void Context::resetNoncacheableConstantBuffer() {
|
||||
NoncacheableConstBuffer.DestroyAll();
|
||||
NoncacheableConstCount = 0;
|
||||
}
|
||||
|
||||
APInt Context::getTag(uint32_t BitWidth, Provenance &Prov) {
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ class Context {
|
|||
// Temporary buffer for non-cacheable constants (e.g.,
|
||||
// undef/ptrtoint/inttoptr).
|
||||
SpecificBumpPtrAllocator<MaterializedConstant> NoncacheableConstBuffer;
|
||||
size_t NoncacheableConstCount = 0;
|
||||
DenseMap<Function *, Pointer> FuncAddrMap;
|
||||
DenseMap<BasicBlock *, Pointer> BlockAddrMap;
|
||||
DenseMap<uint64_t, std::pair<Function *, IntrusiveRefCntPtr<MemoryObject>>>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ TEST(ConcurrentHashTableTest, AddStringEntries) {
|
|||
parallel::TaskGroup tg;
|
||||
|
||||
tg.spawn([&]() {
|
||||
size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
|
||||
std::pair<String *, bool> res1 = HashTable.insert("1");
|
||||
// Check entry is inserted.
|
||||
EXPECT_TRUE(res1.first->getKey() == "1");
|
||||
|
|
@ -79,8 +78,6 @@ TEST(ConcurrentHashTableTest, AddStringEntries) {
|
|||
// Check first entry is still valid.
|
||||
EXPECT_TRUE(res1.first->getKey() == "1");
|
||||
|
||||
// Check data was allocated by allocator.
|
||||
EXPECT_TRUE(Allocator.getBytesAllocated() > AllocatedBytesAtStart);
|
||||
|
||||
// Check statistic.
|
||||
std::string StatisticString;
|
||||
|
|
@ -107,15 +104,10 @@ TEST(ConcurrentHashTableTest, AddStringMultiplueEntries) {
|
|||
tg.spawn([&]() {
|
||||
// Check insertion.
|
||||
for (size_t I = 0; I < NumElements; I++) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0}", I);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_TRUE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() >
|
||||
AllocatedBytesAtStart);
|
||||
}
|
||||
|
||||
std::string StatisticString;
|
||||
|
|
@ -129,16 +121,10 @@ TEST(ConcurrentHashTableTest, AddStringMultiplueEntries) {
|
|||
|
||||
// Check insertion of duplicates.
|
||||
for (size_t I = 0; I < NumElements; I++) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0}", I);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_FALSE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
// Check no additional bytes were allocated for duplicate.
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() ==
|
||||
AllocatedBytesAtStart);
|
||||
}
|
||||
|
||||
// Check statistic.
|
||||
|
|
@ -165,15 +151,10 @@ TEST(ConcurrentHashTableTest, AddStringMultiplueEntriesWithResize) {
|
|||
tg.spawn([&]() {
|
||||
// Check insertion.
|
||||
for (size_t I = 0; I < NumElements; I++) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0} {1}", I, I + 100);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_TRUE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() >
|
||||
AllocatedBytesAtStart);
|
||||
}
|
||||
|
||||
std::string StatisticString;
|
||||
|
|
@ -187,16 +168,10 @@ TEST(ConcurrentHashTableTest, AddStringMultiplueEntriesWithResize) {
|
|||
|
||||
// Check insertion of duplicates.
|
||||
for (size_t I = 0; I < NumElements; I++) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0} {1}", I, I + 100);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_FALSE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
// Check no additional bytes were allocated for duplicate.
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() ==
|
||||
AllocatedBytesAtStart);
|
||||
}
|
||||
|
||||
// Check statistic.
|
||||
|
|
@ -217,15 +192,10 @@ TEST(ConcurrentHashTableTest, AddStringEntriesParallel) {
|
|||
|
||||
// Check parallel insertion.
|
||||
parallelFor(0, NumElements, [&](size_t I) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0}", I);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_TRUE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() >
|
||||
AllocatedBytesAtStart);
|
||||
});
|
||||
|
||||
std::string StatisticString;
|
||||
|
|
@ -239,16 +209,10 @@ TEST(ConcurrentHashTableTest, AddStringEntriesParallel) {
|
|||
|
||||
// Check parallel insertion of duplicates.
|
||||
parallelFor(0, NumElements, [&](size_t I) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0}", I);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_FALSE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
// Check no additional bytes were allocated for duplicate.
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() ==
|
||||
AllocatedBytesAtStart);
|
||||
});
|
||||
|
||||
// Check statistic.
|
||||
|
|
@ -268,15 +232,10 @@ TEST(ConcurrentHashTableTest, AddStringEntriesParallelWithResize) {
|
|||
|
||||
// Check parallel insertion.
|
||||
parallelFor(0, NumElements, [&](size_t I) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0}", I);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_TRUE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() >
|
||||
AllocatedBytesAtStart);
|
||||
});
|
||||
|
||||
std::string StatisticString;
|
||||
|
|
@ -290,16 +249,10 @@ TEST(ConcurrentHashTableTest, AddStringEntriesParallelWithResize) {
|
|||
|
||||
// Check parallel insertion of duplicates.
|
||||
parallelFor(0, NumElements, [&](size_t I) {
|
||||
BumpPtrAllocator &ThreadLocalAllocator =
|
||||
Allocator.getThreadLocalAllocator();
|
||||
size_t AllocatedBytesAtStart = ThreadLocalAllocator.getBytesAllocated();
|
||||
std::string StringForElement = formatv("{0}", I);
|
||||
std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
|
||||
EXPECT_FALSE(Entry.second);
|
||||
EXPECT_TRUE(Entry.first->getKey() == StringForElement);
|
||||
// Check no additional bytes were allocated for duplicate.
|
||||
EXPECT_TRUE(ThreadLocalAllocator.getBytesAllocated() ==
|
||||
AllocatedBytesAtStart);
|
||||
});
|
||||
|
||||
// Check statistic.
|
||||
|
|
|
|||
|
|
@ -110,7 +110,6 @@ TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
|
|||
StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 1), Succeeded());
|
||||
EXPECT_EQ(Str, StringRef("A"));
|
||||
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Tests that a read which crosses a block boundary, but where the subsequent
|
||||
|
|
@ -124,12 +123,10 @@ TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
|
|||
StringRef Str;
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 2), Succeeded());
|
||||
EXPECT_EQ(Str, StringRef("AB"));
|
||||
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
|
||||
|
||||
R.setOffset(6);
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 4), Succeeded());
|
||||
EXPECT_EQ(Str, StringRef("GHIJ"));
|
||||
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Tests that a read which crosses a block boundary and cannot be referenced
|
||||
|
|
@ -143,7 +140,6 @@ TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
|
|||
StringRef Str;
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 10), Succeeded());
|
||||
EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
|
||||
EXPECT_EQ(10U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Test that an out of bounds read which doesn't cross a block boundary
|
||||
|
|
@ -157,7 +153,6 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
|
|||
|
||||
R.setOffset(10);
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 1), Failed());
|
||||
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Test that an out of bounds read which crosses a contiguous block boundary
|
||||
|
|
@ -171,7 +166,6 @@ TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
|
|||
|
||||
R.setOffset(6);
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 5), Failed());
|
||||
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Test that an out of bounds read which crosses a discontiguous block
|
||||
|
|
@ -184,7 +178,6 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
|
|||
StringRef Str;
|
||||
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 11), Failed());
|
||||
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Tests that a read which is entirely contained within a single block but
|
||||
|
|
@ -197,7 +190,6 @@ TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
|
|||
StringRef Str;
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str, 1), Succeeded());
|
||||
EXPECT_EQ(Str, StringRef("A"));
|
||||
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Tests that a read which is not aligned on the same boundary as a previous
|
||||
|
|
@ -212,13 +204,11 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingRead) {
|
|||
StringRef Str2;
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str1, 7), Succeeded());
|
||||
EXPECT_EQ(Str1, StringRef("ABCDEFG"));
|
||||
EXPECT_EQ(7U, F.Allocator.getBytesAllocated());
|
||||
|
||||
R.setOffset(2);
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str2, 3), Succeeded());
|
||||
EXPECT_EQ(Str2, StringRef("CDE"));
|
||||
EXPECT_EQ(Str1.data() + 2, Str2.data());
|
||||
EXPECT_EQ(7U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Tests that a read which is not aligned on the same boundary as a previous
|
||||
|
|
@ -233,12 +223,10 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingReadFail) {
|
|||
StringRef Str2;
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str1, 6), Succeeded());
|
||||
EXPECT_EQ(Str1, StringRef("ABCDEF"));
|
||||
EXPECT_EQ(6U, F.Allocator.getBytesAllocated());
|
||||
|
||||
R.setOffset(4);
|
||||
EXPECT_THAT_ERROR(R.readFixedString(Str2, 4), Succeeded());
|
||||
EXPECT_EQ(Str2, StringRef("EFGH"));
|
||||
EXPECT_EQ(10U, F.Allocator.getBytesAllocated());
|
||||
}
|
||||
|
||||
TEST(MappedBlockStreamTest, WriteBeyondEndOfStream) {
|
||||
|
|
|
|||
|
|
@ -105,24 +105,20 @@ TEST(AllocatorTest, TestAlignment) {
|
|||
// we end up creating a slab for it.
|
||||
TEST(AllocatorTest, TestZero) {
|
||||
BumpPtrAllocator Alloc;
|
||||
Alloc.setRedZoneSize(0); // else our arithmetic is all off
|
||||
Alloc.setRedZoneSize(0); // else the slab count below is off under ASan
|
||||
EXPECT_EQ(0u, Alloc.GetNumSlabs());
|
||||
EXPECT_EQ(0u, Alloc.getBytesAllocated());
|
||||
|
||||
void *Empty = Alloc.Allocate(0, 1);
|
||||
EXPECT_NE(Empty, nullptr) << "Allocate is __attribute__((returns_nonnull))";
|
||||
EXPECT_EQ(1u, Alloc.GetNumSlabs()) << "Allocated a slab to point to";
|
||||
EXPECT_EQ(0u, Alloc.getBytesAllocated());
|
||||
|
||||
void *Large = Alloc.Allocate(4096, 1);
|
||||
EXPECT_EQ(1u, Alloc.GetNumSlabs());
|
||||
EXPECT_EQ(4096u, Alloc.getBytesAllocated());
|
||||
EXPECT_EQ(Empty, Large);
|
||||
|
||||
void *Empty2 = Alloc.Allocate(0, 1);
|
||||
EXPECT_NE(Empty2, nullptr);
|
||||
EXPECT_EQ(1u, Alloc.GetNumSlabs());
|
||||
EXPECT_EQ(4096u, Alloc.getBytesAllocated());
|
||||
}
|
||||
|
||||
// Test allocating just over the slab size. This tests a bug where before the
|
||||
|
|
|
|||
|
|
@ -26,13 +26,11 @@ TEST(PerThreadBumpPtrAllocatorTest, Simple) {
|
|||
(uint64_t *)Allocator.Allocate(sizeof(uint64_t), alignof(uint64_t));
|
||||
*Var = 0xFE;
|
||||
EXPECT_EQ(0xFEul, *Var);
|
||||
EXPECT_EQ(sizeof(uint64_t), Allocator.getBytesAllocated());
|
||||
EXPECT_TRUE(Allocator.getBytesAllocated() <= Allocator.getTotalMemory());
|
||||
EXPECT_LE(sizeof(uint64_t), Allocator.getTotalMemory());
|
||||
|
||||
PerThreadBumpPtrAllocator Allocator2(std::move(Allocator));
|
||||
|
||||
EXPECT_EQ(sizeof(uint64_t), Allocator2.getBytesAllocated());
|
||||
EXPECT_TRUE(Allocator2.getBytesAllocated() <= Allocator2.getTotalMemory());
|
||||
EXPECT_LE(sizeof(uint64_t), Allocator2.getTotalMemory());
|
||||
|
||||
EXPECT_EQ(0xFEul, *Var);
|
||||
});
|
||||
|
|
@ -49,7 +47,7 @@ TEST(PerThreadBumpPtrAllocatorTest, ParallelAllocation) {
|
|||
*ptr = Idx;
|
||||
});
|
||||
|
||||
EXPECT_EQ(sizeof(uint64_t) * NumAllocations, Allocator.getBytesAllocated());
|
||||
EXPECT_LE(sizeof(uint64_t) * NumAllocations, Allocator.getTotalMemory());
|
||||
EXPECT_EQ(Allocator.getNumberOfAllocators(), parallel::getThreadCount());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ TEST(ThreadSafeAllocatorTest, AllocWithAlign) {
|
|||
Threads.wait();
|
||||
|
||||
Alloc.applyLocked([](BumpPtrAllocator &Alloc) {
|
||||
EXPECT_EQ(4950U * sizeof(int), Alloc.getBytesAllocated());
|
||||
EXPECT_LE(4950U * sizeof(int), Alloc.getTotalMemory());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue