aboutsummaryrefslogtreecommitdiff
path: root/pw_allocator/size_report/split_free_list_allocator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'pw_allocator/size_report/split_free_list_allocator.cc')
-rw-r--r--pw_allocator/size_report/split_free_list_allocator.cc131
1 files changed, 131 insertions, 0 deletions
diff --git a/pw_allocator/size_report/split_free_list_allocator.cc b/pw_allocator/size_report/split_free_list_allocator.cc
new file mode 100644
index 000000000..42a51017c
--- /dev/null
+++ b/pw_allocator/size_report/split_free_list_allocator.cc
@@ -0,0 +1,131 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+// This size report uses pw::string::Format and std::snprintf to write a single
+// printf-style string to a buffer. The number of bytes written is returned.
+//
+// This compares the overhead of using pw::string::Format to directly calling
+// std::snprintf and determining the number of bytes written. It demonstrates
+// that the code for using pw::string::Format is much simpler.
+
+#include "pw_allocator/split_free_list_allocator.h"
+
+#include "pw_bloat/bloat_this_binary.h"
+
+#ifdef SIZE_REPORT_METRIC_PROXY
+#include "pw_allocator/allocator_metric_proxy.h"
+#endif // SIZE_REPORT_METRIC_PROXY
+
+namespace {
+
+pw::allocator::SplitFreeListAllocator allocator;
+
+#ifdef SIZE_REPORT_METRIC_PROXY
+pw::allocator::AllocatorMetricProxy proxy(0);
+#endif // SIZE_REPORT_METRIC_PROXY
+
+constexpr void* kFakeMemoryRegionStart = &allocator;
+constexpr size_t kFakeMemoryRegionSize = 4096;
+
+constexpr size_t kSplitFreeListThreshold = 128;
+
+} // namespace
+
+int main() {
+ pw::bloat::BloatThisBinary();
+
+ allocator.Init(
+ pw::ByteSpan(reinterpret_cast<std::byte*>(kFakeMemoryRegionStart),
+ kFakeMemoryRegionSize),
+ kSplitFreeListThreshold);
+
+ struct Foo {
+ char name[16];
+ };
+ struct Bar : public Foo {
+ int number;
+ };
+
+ // Small allocation.
+ Foo* foo =
+ static_cast<Foo*>(allocator.Allocate(pw::allocator::Layout::Of<Foo>()));
+ if (foo == nullptr) {
+ return 1;
+ }
+
+ foo->name[0] = '\0';
+
+ // Reallocate.
+ Bar* bar = static_cast<Bar*>(
+ allocator.Reallocate(foo, pw::allocator::Layout::Of<Foo>(), sizeof(Bar)));
+ if (bar == nullptr) {
+ return 1;
+ }
+
+ bar->number = 4;
+
+ // Large allocation.
+ struct Baz {
+ std::byte data[kSplitFreeListThreshold * 2];
+ };
+ Baz* baz =
+ static_cast<Baz*>(allocator.Allocate(pw::allocator::Layout::Of<Baz>()));
+ if (baz == nullptr) {
+ return 1;
+ }
+
+ baz->data[kSplitFreeListThreshold] = std::byte(0xf1);
+
+ // Deallocate.
+ allocator.Deallocate(bar, pw::allocator::Layout::Of<Bar>());
+ allocator.Deallocate(baz, pw::allocator::Layout::Of<Baz>());
+
+#ifdef SIZE_REPORT_UNIQUE_PTR
+
+ struct Point {
+ int x;
+ int y;
+
+ Point(int xx, int yy) : x(xx), y(yy) {}
+ };
+
+ {
+ std::optional<pw::allocator::UniquePtr<Point>> maybe_point =
+ allocator.MakeUnique<Point>(3, 4);
+ if (!maybe_point.has_value()) {
+ return 1;
+ }
+
+ pw::allocator::UniquePtr<Point> point = *maybe_point;
+ point->x = point->y * 2;
+ }
+
+#endif // SIZE_REPORT_UNIQUE_PTR
+
+#ifdef SIZE_REPORT_METRIC_PROXY
+ proxy.Initialize(allocator);
+
+ Foo* foo2 =
+ static_cast<Foo*>(proxy.Allocate(pw::allocator::Layout::Of<Foo>()));
+ if (foo2 == nullptr) {
+ return 1;
+ }
+
+ foo2->name[1] = 'a';
+
+ proxy.Deallocate(foo2, pw::allocator::Layout::Of<Foo>());
+#endif // SIZE_REPORT_METRIC_PROXY
+
+ return 0;
+}