Skip to content

Commit

Permalink
pw_containers: Make size_reports more reusable
Browse files Browse the repository at this point in the history
The pw_containers size reports were added with the intention that they
could be used in setting baselines for size reports of other modules
that depended on them. On attempting that, it became apparent that the
intrusive container size reports were too opinionated about their items.
This CL adjusts the reports to use iterators to add items to containers
instead. It also skips certain operations that require items to have
certain traits, e.g. moveability or well-orderedness.

Change-Id: I4d87ed27b374f8ceec79bb5702bdb058ef875c12
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/267813
Reviewed-by: Wyatt Hepler <[email protected]>
Lint: Lint 🤖 <[email protected]>
Docs-Not-Needed: Aaron Green <[email protected]>
Pigweed-Auto-Submit: Aaron Green <[email protected]>
Commit-Queue: Aaron Green <[email protected]>
  • Loading branch information
nopsledder authored and CQ Bot Account committed Feb 14, 2025
1 parent 7ab1856 commit 1650a4b
Show file tree
Hide file tree
Showing 26 changed files with 188 additions and 104 deletions.
4 changes: 2 additions & 2 deletions pw_allocator/public/pw_allocator/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class Allocator : public Deallocator {
/// pointer.
///
/// @param[in] args... Arguments passed to the object constructor.
template <typename T, int&... ExplicitGuard, typename... Args>
template <typename T, int&... kExplicitGuard, typename... Args>
T* New(Args&&... args) {
void* ptr = Allocate(Layout::Of<T>());
if (ptr == nullptr) {
Expand Down Expand Up @@ -95,7 +95,7 @@ class Allocator : public Deallocator {
/// fails. Callers must check for null before using the `UniquePtr`.
///
/// @param[in] args... Arguments passed to the object constructor.
template <typename T, int&... ExplicitGuard, typename... Args>
template <typename T, int&... kExplicitGuard, typename... Args>
[[nodiscard]] UniquePtr<T> MakeUnique(Args&&... args) {
return Deallocator::WrapUnique<T>(New<T>(std::forward<Args>(args)...));
}
Expand Down
4 changes: 2 additions & 2 deletions pw_allocator/public/pw_allocator/bump_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class BumpAllocator : public Allocator {
/// pointer.
///
/// @param[in] args... Arguments passed to the object constructor.
template <typename T, int&... ExplicitGuard, typename... Args>
template <typename T, int&... kExplicitGuard, typename... Args>
T* NewOwned(Args&&... args) {
internal::Owned<T>* owned = New<internal::Owned<T>>();
T* ptr = owned != nullptr ? New<T>(std::forward<Args>(args)...) : nullptr;
Expand All @@ -120,7 +120,7 @@ class BumpAllocator : public Allocator {
/// fails. Callers must check for null before using the `UniquePtr`.
///
/// @param[in] args... Arguments passed to the object constructor.
template <typename T, int&... ExplicitGuard, typename... Args>
template <typename T, int&... kExplicitGuard, typename... Args>
[[nodiscard]] UniquePtr<T> MakeUniqueOwned(Args&&... args) {
return WrapUnique<T>(NewOwned<T>(std::forward<Args>(args)...));
}
Expand Down
4 changes: 2 additions & 2 deletions pw_allocator/public/pw_allocator/typed_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class TypedPool : public ChunkPool {
/// to the pool's object type.
///
/// @param[in] args... Arguments passed to the object constructor.
template <int&... ExplicitGuard, typename... Args>
template <int&... kExplicitGuard, typename... Args>
T* New(Args&&... args) {
void* ptr = Allocate();
return ptr != nullptr ? new (ptr) T(std::forward<Args>(args)...) : nullptr;
Expand All @@ -101,7 +101,7 @@ class TypedPool : public ChunkPool {
/// specific to the pool's object type.
///
/// @param[in] args... Arguments passed to the object constructor.
template <int&... ExplicitGuard, typename... Args>
template <int&... kExplicitGuard, typename... Args>
UniquePtr<T> MakeUnique(Args&&... args) {
return Deallocator::WrapUnique<T>(New(std::forward<Args>(args)...));
}
Expand Down
24 changes: 24 additions & 0 deletions pw_containers/public/pw_containers/internal/intrusive_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,28 @@ struct IntrusiveItem<Item, T, true> {
using Type = typename T::ItemType;
};

// Implementation of `is_weakly_orderable` that uses SFINE to detect when the
// given type can be ordered using the '<' operator.
template <typename T>
struct is_weakly_orderable_impl {
template <typename U>
static decltype(std::declval<U>() < std::declval<U>()) deduce(T*);

template <typename>
static std::false_type deduce(...);

using type = typename std::is_same<bool, decltype(deduce<T>(nullptr))>::type;
};

/// Checks if a type can be compared with the less-than operator, '<'.
///
/// If `T` satisfies \em LessThanComparable, provides the member constant
/// value equal to true. Otherwise value is false.
template <typename T>
struct is_weakly_orderable : is_weakly_orderable_impl<T>::type {};

/// Helper variable template for `is_weakly_orderable<T>::value`.
template <typename T>
inline constexpr bool is_weakly_orderable_v = is_weakly_orderable<T>::value;

} // namespace pw::containers::internal
6 changes: 4 additions & 2 deletions pw_containers/size_report/inline_deque.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureInlineDeque<V1>(mask);
auto& items1 = GetItems<V1>();
int rc = MeasureInlineDeque<V1>(items1.begin(), items1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureInlineDeque<V2>(mask);
auto& items2 = GetItems<V2>();
rc += MeasureInlineDeque<V2>(items2.begin(), items2.end(), mask);
#endif

return rc;
Expand Down
4 changes: 3 additions & 1 deletion pw_containers/size_report/inline_deque_and_queue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
return MeasureInlineDeque<V1>(mask) + MeasureInlineQueue<V1>(mask);
auto& items = GetItems<V1>();
return MeasureInlineDeque<V1>(items.begin(), items.end(), mask) +
MeasureInlineQueue<V1>(items.begin(), items.end(), mask);
}

} // namespace pw::containers::size_report
Expand Down
6 changes: 4 additions & 2 deletions pw_containers/size_report/inline_queue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureInlineQueue<V1>(mask);
auto& items1 = GetItems<V1>();
int rc = MeasureInlineQueue<V1>(items1.begin(), items1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureInlineQueue<V2>(mask);
auto& items2 = GetItems<V2>();
rc += MeasureInlineQueue<V2>(items2.begin(), items2.end(), mask);
#endif

return rc;
Expand Down
8 changes: 6 additions & 2 deletions pw_containers/size_report/intrusive_forward_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureIntrusiveForwardList<ForwardListItem<V1>>(mask);
auto& items1 = GetItems<ForwardListItem<V1>>();
int rc = MeasureIntrusiveForwardList<ForwardListItem<V1>>(
items1.begin(), items1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureIntrusiveForwardList<ForwardListItem<V2>>(mask);
auto& items2 = GetItems<ForwardListItem<V2>>();
rc += MeasureIntrusiveForwardList<ForwardListItem<V2>>(
items2.begin(), items2.end(), mask);
#endif

return rc;
Expand Down
7 changes: 5 additions & 2 deletions pw_containers/size_report/intrusive_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureIntrusiveList<ListItem<V1>>(mask);
auto& items1 = GetItems<ListItem<V1>>();
int rc =
MeasureIntrusiveList<ListItem<V1>>(items1.begin(), items1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureIntrusiveList<ListItem<V2>>(mask);
auto& items2 = GetItems<ListItem<V2>>();
rc += MeasureIntrusiveList<ListItem<V2>>(items2.begin(), items2.end(), mask);
#endif

return rc;
Expand Down
8 changes: 6 additions & 2 deletions pw_containers/size_report/intrusive_list_and_forward_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
return MeasureIntrusiveList<ListItem<V1>>(mask) +
MeasureIntrusiveForwardList<ForwardListItem<V1>>(mask);
auto& items1 = GetItems<ListItem<V1>>();
auto& items2 = GetItems<ForwardListItem<V1>>();
return MeasureIntrusiveList<ListItem<V1>>(
items1.begin(), items1.end(), mask) +
MeasureIntrusiveForwardList<ForwardListItem<V1>>(
items2.begin(), items2.end(), mask);
}

} // namespace pw::containers::size_report
Expand Down
12 changes: 9 additions & 3 deletions pw_containers/size_report/intrusive_map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureIntrusiveMap<MapPair<K1, V1>>(mask);
auto& pairs1 = GetPairs<MapPair<K1, V1>>();
int rc = MeasureIntrusiveMap<K1, MapPair<K1, V1>>(
pairs1.begin(), pairs1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureIntrusiveMap<MapPair<K1, V2>>(mask);
auto& pairs2 = GetPairs<MapPair<K1, V2>>();
rc += MeasureIntrusiveMap<K1, MapPair<K1, V2>>(
pairs2.begin(), pairs2.end(), mask);
#endif

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_KEY_AND_VALUE
rc += MeasureIntrusiveMap<MapPair<K2, V2>>(mask);
auto& pairs3 = GetPairs<MapPair<K2, V2>>();
rc += MeasureIntrusiveMap<K2, MapPair<K2, V2>>(
pairs3.begin(), pairs3.end(), mask);
#endif

return rc;
Expand Down
8 changes: 6 additions & 2 deletions pw_containers/size_report/intrusive_map_and_multimap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
return MeasureIntrusiveMap<MapPair<K1, V1>>(mask) +
MeasureIntrusiveMultiMap<MultiMapPair<K1, V1>>(mask);
auto& pairs1 = GetPairs<MapPair<K1, V1>>();
auto& pairs2 = GetPairs<MultiMapPair<K1, V1>>();
return MeasureIntrusiveMap<K1, MapPair<K1, V1>>(
pairs1.begin(), pairs1.end(), mask) +
MeasureIntrusiveMultiMap<K1, MultiMapPair<K1, V1>>(
pairs2.begin(), pairs2.end(), mask);
}

} // namespace pw::containers::size_report
Expand Down
12 changes: 9 additions & 3 deletions pw_containers/size_report/intrusive_multimap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureIntrusiveMultiMap<MultiMapPair<K1, V1>>(mask);
auto& pairs1 = GetPairs<MultiMapPair<K1, V1>>();
int rc = MeasureIntrusiveMultiMap<K1, MultiMapPair<K1, V1>>(
pairs1.begin(), pairs1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureIntrusiveMultiMap<MultiMapPair<K1, V2>>(mask);
auto& pairs2 = GetPairs<MultiMapPair<K1, V1>>();
rc += MeasureIntrusiveMultiMap<K1, MultiMapPair<K1, V2>>(
pairs2.begin(), pairs2.end(), mask);
#endif
#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_KEY_AND_VALUE
rc += MeasureIntrusiveMap<MultiMapPair<K2, V2>>(mask);
auto& pairs3 = GetPairs<MultiMapPair<K1, V1>>();
rc += MeasureIntrusiveMap<K2, MultiMapPair<K2, V2>>(
pairs3.begin(), pairs3.end(), mask);
#endif

return rc;
Expand Down
8 changes: 6 additions & 2 deletions pw_containers/size_report/intrusive_multiset.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureIntrusiveMultiSet<MultiSetItem<V1>>(mask);
auto& items1 = GetItems<MultiSetItem<V1>>();
int rc = MeasureIntrusiveMultiSet<MultiSetItem<V1>>(
items1.begin(), items1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureIntrusiveMultiSet<MultiSetItem<V2>>(mask);
auto& items2 = GetItems<MultiSetItem<V2>>();
rc += MeasureIntrusiveMultiSet<MultiSetItem<V2>>(
items2.begin(), items2.end(), mask);
#endif

return rc;
Expand Down
6 changes: 4 additions & 2 deletions pw_containers/size_report/intrusive_set.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
int rc = MeasureIntrusiveSet<SetItem<V1>>(mask);
auto& items1 = GetItems<SetItem<V1>>();
int rc = MeasureIntrusiveSet<SetItem<V1>>(items1.begin(), items1.end(), mask);

#ifdef PW_CONTAINERS_SIZE_REPORT_ALTERNATE_VALUE
rc += MeasureIntrusiveSet<SetItem<V2>>(mask);
auto& items2 = GetItems<SetItem<V2>>();
rc += MeasureIntrusiveSet<SetItem<V2>>(items2.begin(), items2.end(), mask);
#endif

return rc;
Expand Down
7 changes: 5 additions & 2 deletions pw_containers/size_report/intrusive_set_and_multiset.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ namespace pw::containers::size_report {

int Measure() {
volatile uint32_t mask = bloat::kDefaultMask;
return MeasureIntrusiveSet<SetItem<V1>>(mask) +
MeasureIntrusiveMultiSet<MultiSetItem<V1>>(mask);
auto& items1 = GetItems<SetItem<V1>>();
auto& items2 = GetItems<MultiSetItem<V1>>();
return MeasureIntrusiveSet<SetItem<V1>>(items1.begin(), items1.end(), mask) +
MeasureIntrusiveMultiSet<MultiSetItem<V1>>(
items2.begin(), items2.end(), mask);
}

} // namespace pw::containers::size_report
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ namespace pw::containers::size_report {
/// This method is used both to measure inline deques directly, as well as to
/// provide a baseline for measuring other types that use inline deques and want
/// to only measure their contributions to code size.
template <typename T>
int MeasureInlineDeque(uint32_t mask) {
template <typename T, int&... kExplicitGuard, typename Iterator>
int MeasureInlineDeque(Iterator first, Iterator last, uint32_t mask) {
mask = SetBaseline(mask);
auto& inline_deque = GetContainer<InlineDeque<T, kNumItems>>();
const auto& items = GetItems<T>();
inline_deque.assign(items.begin(), items.end());
inline_deque.assign(first, last);
mask = MeasureContainer(inline_deque, mask);
PW_BLOAT_COND(inline_deque.full(), mask);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ namespace pw::containers::size_report {
/// This method is used both to measure inline queues directly, as well as to
/// provide a baseline for measuring other types that use inline queues and want
/// to only measure their contributions to code size.
template <typename T>
int MeasureInlineQueue(uint32_t mask) {
template <typename T, int&... kExplicitGuard, typename Iterator>
int MeasureInlineQueue(Iterator first, Iterator last, uint32_t mask) {
mask = SetBaseline(mask);
auto& inline_queue = GetContainer<InlineQueue<T, kNumItems>>();
const auto& items = GetItems<T>();
for (auto& item : items) {
inline_queue.push_overwrite(item);
while (first != last) {
inline_queue.push_overwrite(*first++);
}
mask = MeasureContainer(inline_queue, mask);
PW_BLOAT_COND(inline_queue.full(), mask);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,34 @@ struct ForwardListItem : public IntrusiveForwardList<ForwardListItem<T>>::Item {
/// This method is used both to measure intrusive forward lists directly, as
/// well as to provide a baseline for measuring other types that use intrusive
/// forward lists and want to only measure their contributions to code size.
template <typename ItemType>
int MeasureIntrusiveForwardList(uint32_t mask) {
template <typename ItemType, int&... kExplicitGuard, typename Iterator>
int MeasureIntrusiveForwardList(Iterator first, Iterator last, uint32_t mask) {
mask = SetBaseline(mask);
auto& list1 = GetContainer<IntrusiveForwardList<ItemType>>();
IntrusiveForwardList<ItemType> list2;
auto& items = GetItems<ItemType>();
auto iter1 = items.begin() + 3;
list1.assign(items.begin(), iter1);
list2.assign(iter1, items.end());
auto iter1 = first;
for (size_t i = 0; i < 3; ++i) {
if (iter1 != last) {
++iter1;
}
}
list1.assign(first, iter1);
list2.assign(iter1, last);

auto& item1 = list1.front();
PW_BLOAT_EXPR(list1.pop_front(), mask);
PW_BLOAT_EXPR(list2.push_front(item1), mask);
PW_BLOAT_EXPR(list1.swap(list2), mask);
PW_BLOAT_EXPR(list1.sort(), mask);
PW_BLOAT_EXPR(list1.reverse(), mask);
PW_BLOAT_EXPR(list1.merge(list2), mask);
if constexpr (std::is_move_assignable_v<ItemType>) {
PW_BLOAT_EXPR(list1.swap(list2), mask);
PW_BLOAT_EXPR(list1.reverse(), mask);
}
if constexpr (internal::is_weakly_orderable_v<ItemType>) {
PW_BLOAT_EXPR(list1.sort(), mask);
PW_BLOAT_EXPR(list1.merge(list2), mask);
PW_BLOAT_COND(list1.unique() != 0, mask);
}
PW_BLOAT_EXPR(list2.clear(), mask);
PW_BLOAT_EXPR(list1.remove(item1), mask);
PW_BLOAT_COND(list1.unique() != 0, mask);

ItemType& item2 = list1.front();
auto iter2 = list1.erase_after(list1.before_begin());
Expand Down
Loading

0 comments on commit 1650a4b

Please sign in to comment.