21#include "pw_allocator/allocator.h"
22#include "pw_allocator/block/small_block.h"
23#include "pw_allocator/block_allocator.h"
24#include "pw_bloat/bloat_this_binary.h"
25#include "pw_bytes/span.h"
27namespace pw::allocator::size_report {
30using BlockType = SmallBlock;
34 std::array<std::byte, 16> buffer;
42 Bar(
size_t number_) : number(number_) {
43 std::memset(foo.buffer.data(), 0, foo.buffer.size());
60int SetBaseline(uint32_t mask);
67template <
typename BlockType>
68int MeasureBlock(uint32_t mask);
75template <
typename BucketType>
76int MeasureBucket(BucketType& bucket, uint32_t mask);
83int MeasureAllocator(
Allocator& allocator, uint32_t mask);
94template <
typename BlockType>
95int MeasureBlock(uint32_t mask) {
96 if (SetBaseline(mask) != 0) {
101 auto result = BlockType::Init(GetBuffer());
102 BlockType* block = *result;
105 std::byte* bytes = block->UsableSpace();
108 block = BlockType::FromUsableSpace(bytes);
110 if constexpr (is_allocatable_v<BlockType>) {
112 Layout foo = Layout::Of<Foo>();
113 auto block_result = BlockType::AllocFirst(std::move(block), foo);
114 if (!block_result.ok()) {
118 BlockType* first_block = block_result.block();
119 block = first_block->Next();
122 if constexpr (is_alignable_v<BlockType>) {
123 constexpr Layout kOverlyAligned(128, 64);
124 block_result = BlockType::AllocLast(std::move(block), kOverlyAligned);
126 Layout baz = Layout::Of<Baz>();
127 block_result = BlockType::AllocLast(std::move(block), baz);
129 if (!block_result.ok()) {
133 BlockType* last_block = block_result.block();
134 block = last_block->Prev();
137 block_result = block->Resize(
sizeof(Bar));
138 if (!block_result.ok()) {
143 block_result = BlockType::Free(std::move(first_block));
144 return block_result.ok() ? 0 : 1;
148template <
typename BucketType>
149int MeasureBucket(BucketType& bucket, uint32_t mask) {
150 if (
int rc = SetBaseline(mask); rc != 0) {
153 if (
int rc = MeasureBlock<BlockType>(mask); rc != 0) {
157 auto result = BlockType::Init(GetBuffer());
158 BlockType* unallocated = *result;
161 std::array<BlockType*, 4> blocks;
162 for (
size_t i = 0; i < blocks.size(); ++i) {
163 Layout layout(16 * (i + 1), 1);
164 auto block_result = BlockType::AllocFirst(std::move(unallocated), layout);
165 blocks[i] = block_result.block();
166 unallocated = blocks[i]->Next();
167 PW_BLOAT_COND(bucket.Add(*blocks[i]), mask);
171 PW_BLOAT_COND(bucket.Remove(*blocks[0]), mask);
174 BlockType* compatible = bucket.RemoveCompatible(Layout(32, 1));
175 PW_BLOAT_COND(compatible !=
nullptr, mask);
178 BlockType* any_block = bucket.RemoveAny();
179 PW_BLOAT_COND(any_block !=
nullptr, mask);
182 PW_BLOAT_COND(!bucket.empty(), mask);
183 PW_BLOAT_EXPR(bucket.Clear(), mask);
184 return bucket.empty() ? 0 : 1;
Definition: allocator.h:34
Definition: block_allocator.h:104
Type used for exercising an allocator.
Definition: size_report.h:38
Type used for exercising an allocator.
Definition: size_report.h:48
Type used for exercising an allocator.
Definition: size_report.h:33