Skip to content

Commit e9beaa7

Browse files
committed
Merge bitcoin/bitcoin#28913: coins: make sure PoolAllocator uses the correct alignment
d5b4c0b pool: change memusage_test to use int64_t, add allocation check (Martin Leitner-Ankerl) ce881bf pool: make sure PoolAllocator uses the correct alignment (Martin Leitner-Ankerl) Pull request description: The class `CTxOut` has a member `CAmount` which is an int64_t, and on ARM 32bit int64_t are 8 byte aligned, which is larger than the pointer alignment of 4 bytes. So for `CCoinsMap` to be able to use the pool, we need to use the alignment of the member instead of just `alignof(void*)`. This fixes #28906 (first noted in bitcoin/bitcoin#28718 (comment)) and #28440. ACKs for top commit: pinheadmz: ACK d5b4c0b hebasto: re-ACK d5b4c0b, the only change since my recent [review](bitcoin/bitcoin#28913 (review)) is an updated test. theStack: Tested ACK d5b4c0b Tree-SHA512: 4446793fad6d56f0fe22e09ac9ade051e86de11ac039cd61c0f6b7f79874242878a6a46a2c76ac3b8f1d53464872620d39139f54b1471daccad26d6bb1ae8ca1
2 parents 640b450 + d5b4c0b commit e9beaa7

File tree

4 files changed

+17
-15
lines changed

4 files changed

+17
-15
lines changed

src/bench/pool.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ static void PoolAllocator_StdUnorderedMapWithPoolResource(benchmark::Bench& benc
3737
std::hash<uint64_t>,
3838
std::equal_to<uint64_t>,
3939
PoolAllocator<std::pair<const uint64_t, uint64_t>,
40-
sizeof(std::pair<const uint64_t, uint64_t>) + 4 * sizeof(void*),
41-
alignof(void*)>>;
40+
sizeof(std::pair<const uint64_t, uint64_t>) + 4 * sizeof(void*)>>;
4241

4342
// make sure the resource supports large enough pools to hold the node. We do this by adding the size of a few pointers to it.
4443
auto pool_resource = Map::allocator_type::ResourceType();

src/coins.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,7 @@ using CCoinsMap = std::unordered_map<COutPoint,
145145
SaltedOutpointHasher,
146146
std::equal_to<COutPoint>,
147147
PoolAllocator<std::pair<const COutPoint, CCoinsCacheEntry>,
148-
sizeof(std::pair<const COutPoint, CCoinsCacheEntry>) + sizeof(void*) * 4,
149-
alignof(void*)>>;
148+
sizeof(std::pair<const COutPoint, CCoinsCacheEntry>) + sizeof(void*) * 4>>;
150149

151150
using CCoinsMapMemoryResource = CCoinsMap::allocator_type::ResourceType;
152151

src/support/allocators/pool.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ class PoolResource final
272272
/**
273273
* Forwards all allocations/deallocations to the PoolResource.
274274
*/
275-
template <class T, std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES>
275+
template <class T, std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES = alignof(T)>
276276
class PoolAllocator
277277
{
278278
PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>* m_resource;

src/test/pool_tests.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,21 +156,20 @@ BOOST_AUTO_TEST_CASE(random_allocations)
156156

157157
BOOST_AUTO_TEST_CASE(memusage_test)
158158
{
159-
auto std_map = std::unordered_map<int, int>{};
160-
161-
using Map = std::unordered_map<int,
162-
int,
163-
std::hash<int>,
164-
std::equal_to<int>,
165-
PoolAllocator<std::pair<const int, int>,
166-
sizeof(std::pair<const int, int>) + sizeof(void*) * 4,
167-
alignof(void*)>>;
159+
auto std_map = std::unordered_map<int64_t, int64_t>{};
160+
161+
using Map = std::unordered_map<int64_t,
162+
int64_t,
163+
std::hash<int64_t>,
164+
std::equal_to<int64_t>,
165+
PoolAllocator<std::pair<const int64_t, int64_t>,
166+
sizeof(std::pair<const int64_t, int64_t>) + sizeof(void*) * 4>>;
168167
auto resource = Map::allocator_type::ResourceType(1024);
169168

170169
PoolResourceTester::CheckAllDataAccountedFor(resource);
171170

172171
{
173-
auto resource_map = Map{0, std::hash<int>{}, std::equal_to<int>{}, &resource};
172+
auto resource_map = Map{0, std::hash<int64_t>{}, std::equal_to<int64_t>{}, &resource};
174173

175174
// can't have the same resource usage
176175
BOOST_TEST(memusage::DynamicUsage(std_map) != memusage::DynamicUsage(resource_map));
@@ -182,6 +181,11 @@ BOOST_AUTO_TEST_CASE(memusage_test)
182181

183182
// Eventually the resource_map should have a much lower memory usage because it has less malloc overhead
184183
BOOST_TEST(memusage::DynamicUsage(resource_map) <= memusage::DynamicUsage(std_map) * 90 / 100);
184+
185+
// Make sure the pool is actually used by the nodes
186+
auto max_nodes_per_chunk = resource.ChunkSizeBytes() / sizeof(Map::value_type);
187+
auto min_num_allocated_chunks = resource_map.size() / max_nodes_per_chunk + 1;
188+
BOOST_TEST(resource.NumAllocatedChunks() >= min_num_allocated_chunks);
185189
}
186190

187191
PoolResourceTester::CheckAllDataAccountedFor(resource);

0 commit comments

Comments
 (0)