Code size analysis#

pw_async2: Cooperative async tasks for embedded

Core async2 implementation#

The following table shows the code size cost of adding pw_async2 to a system. These size reports assume a baseline system with an RTOS which already uses a handful of core Pigweed components including HAL abstractions and pw_allocator.

The first row captures the core of pw_async2: the dispatcher, tasks, and wakers, using the pw::async2::BasicDispatcher. This is the minimum size cost a system must pay to adopt pw_async2. The following row demonstrates the cost of adding another task to this system. Of course, the majority of the cost of the task exists within its implementation — this simply shows that there is minimal internal overhead.

Label

Segment

Delta

Full cost of including pw_async2

FLASH

+884

[section .rodata]

-2

std::__2::__cxx_atomic_compare_exchange_weak[abi:nqn240000]<>()

+2

pw::Allocator::DoReallocate()

-2

pw::GetAlignedSubspan()

+40

pw::containers::internal::GenericIntrusiveList<>::remove_if<>()

+4

__aeabi_dcmpun

+232

pw::async2::size_report::Measure()

+14

pw::containers::internal::GenericIntrusiveList<>::remove()

NEW

+184

pw::async2::Task::RunInDispatcher()

NEW

+100

pw::async2::Dispatcher::~Dispatcher()

NEW

+100

pw::this_thread::sleep_for()

NEW

+96

pw::async2::Task::TryDeregister()

NEW

+88

pw::async2::Dispatcher::Post()

NEW

+88

pw::async2::Dispatcher::Terminate()

NEW

+84

pw::SharedPtr<>::reset()

NEW

+82

pw::async2::Task::~Task()

NEW

+76

pw::async2::Dispatcher::Wake()

NEW

+76

pw::async2::Task::Wake()

NEW

+76

vTaskDelay

NEW

+72

pw::async2::size_report::PendableValue<>::Get()

NEW

+64

pw::async2::Waker::TrySetTask()

NEW

+60

pw::async2::Waker::operator=()

NEW

+60

pw::this_thread::get_id()

NEW

+56

pw::async2::Dispatcher::PopTaskToRun()

NEW

+56

pw::async2::Task::PostTo()

NEW

+52

pw::async2::size_report::MockTask::DoPend()

NEW

+46

pw::async2::size_report::MockTask::~MockTask()

NEW

+44

pw::async2::Task::UnpostAndReleaseRefFromDispatcherDestructor()

NEW

+44

pw::async2::Waker::Wake()

NEW

+42

pw::containers::internal::GenericIntrusiveQueue::remove()

NEW

+40

__atomic_fetch_add_1

NEW

+40

__atomic_fetch_sub_1

NEW

+40

__atomic_fetch_sub_4

NEW

+36

pw::allocator::internal::ControlBlock::DecrementShared()

NEW

+36

pw::async2::Task::UnpostAndReleaseRef()

NEW

+34

pw::async2::Dispatcher::DeregisterTask()

NEW

+32

__atomic_load_1

NEW

+32

pw::async2::Dispatcher::PopTaskToRunLocked()

NEW

+32

pw::async2::Waker::Clear()

NEW

+30

pw::async2::BasicDispatcher::~BasicDispatcher()

NEW

+30

pw::async2::FuncTask<>::~FuncTask()

NEW

+28

pw::allocator::internal::ControlBlock::~ControlBlock()

NEW

+28

pw::async2::BasicDispatcher

NEW

+28

pw::async2::Dispatcher::PopAndRunAllReadyTasks()

NEW

+28

pw::async2::RunnableDispatcher::RunToCompletion()

NEW

+26

pw::async2::Dispatcher::UnpostTaskList()

NEW

+26

pw::containers::internal::GenericIntrusiveQueue::insert_after()

NEW

+24

pw::async2::Task::Deregister()

NEW

+22

pw::async2::Task::RemoveAllWakersLocked()

NEW

+22

pw::async2::Task::Unpost()

NEW

+22

pw::async2::Waker::RemoveTask()

NEW

+20

pw::async2::Dispatcher

NEW

+20

pw::async2::FuncTask<>

NEW

+20

pw::async2::Task

NEW

+20

pw::async2::size_report::MockTask

NEW

+20

pw::async2::size_report::MockTask::DoPend()::{lambda()#1}::operator()()

NEW

+20

pw::async2::size_report::PendableValue<>::Get()::{lambda()#1}::operator()()

NEW

+20

pw::containers::internal::GenericIntrusiveQueue::erase_after()

NEW

+18

pw::async2::FuncTask<>::DoPend()

NEW

+16

pw::async2::Task::ReleaseSharedRef()

NEW

+16

pw::async2::Waker::~Waker()

NEW

+14

pw::allocator::internal::BaseManagedPtr::Deallocate()

NEW

+14

pw::async2::Waker::RemoveTaskIfSet()

NEW

+14

pw::async2::internal::YieldToAnyThread()

NEW

+14

pw::containers::internal::GenericIntrusiveQueue::push_back()

NEW

+12

pw::containers::internal::GenericIntrusiveQueue::push_front()

NEW

+10

pw::allocator::internal::BaseManagedPtr::HasCapability()

NEW

+10

pw::async2::BasicDispatcher::DoWaitForWake()

NEW

+10

pw::async2::BasicDispatcher::DoWake()

NEW

+10

pw::containers::internal::GenericIntrusiveQueue::pop_front()

NEW

+8

pw::allocator::internal::BaseManagedPtr::Resize()

NEW

+8

pw::async2::RunnableDispatcher::DoRunUntilStalled()

+3,768

RAM

NEW

+32

pw::async2::size_report::(anonymous namespace)::dispatcher

NEW

+8

pw::async2::internal::lock()::lock

+40

Base incremental cost of adding a task to an existing async system

FLASH

+56

pw::async2::size_report::Measure()

-8

vPortSVCHandler_C

+48

Size of pw_async2’s C++ coroutine adapters

FLASH

+268

[section .rodata]

+108

pw::async2::size_report::Measure()

+2

pw::async2::FuncTask<>::~FuncTask()

NEW

+208

pw::async2::size_report::StoresFiveThenReturns()

NEW

+144

pw::async2::Coro<>::Pend()

NEW

+84

pw::async2::size_report::ImmediatelyReturnsFive()

NEW

+60

pw::async2::internal::Awaitable<>::Advance()

NEW

+56

pw::async2::internal::Awaitable<>::await_suspend()

NEW

+48

pw::async2::CoroTask<>::DoPend()

NEW

+42

pw::async2::internal::CoroPromiseBase::SharedNew()

NEW

+42

pw::containers::internal::OptionalData<>::operator=()

NEW

+40

pw::async2::CoroTask<>::~CoroTask()

NEW

+36

pw::containers::internal::OptionalData<>::AssignState()

NEW

+32

pw::async2::internal::CrashDueToCoroutineAllocationFailure()

NEW

+28

pw::async2::internal::CoroPromiseBase::AdvanceAwaitable()

NEW

+26

pw::async2::internal::CoroPromiseBase::SharedDelete()

NEW

+20

pw::async2::CoroTask<>

NEW

+16

pw::async2::internal::CoroPromiseBase::operator new<>()

NEW

+12

pw::async2::internal::CoroPromiseBase::operator delete()

NEW

+8

pw::async2::internal::CoroPromiseBase::SuspendAwaitable<>()::{lambda()#1}::__invoke()

+1,280

Futures#

Futures are the core abstraction in pw_async2, providing a standardized way of polling an asynchronous operation to completion.

An important consideration for code size is that all futures are templated on the type of value they produce, which means that the compiler must generate separate code for each type. Pigweed attempts to share common operations through non-templated utilities like FutureCore and makes several optimizations to commonly used future types.

The following sections detail the code size of various future implementations and utilities.

ValueFuture#

ValueFuture is the simplest future type, used to return a single result from an asynchronous operation. Its implementation contains effectively the minimal code required for a future, making it a good baseline for understanding the size cost of a future in pw_async2.

The table below shows the size of ValueFuture. The first row shows the base cost of using a single ValueFuture. The second row adds another ValueFuture with a different return type to demonstrate the incremental cost of template specialization. The third row shows the size of VoidFuture (alias for ValueFuture<void>), which is specialized to avoid storing a value.

Label

Segment

Delta

Size of ValueFuture

FLASH

+220

[section .rodata]

-92

pw::async2::size_report::Measure()

DEL

-72

pw::async2::size_report::PendableValue<>::Get()

-4

vPortSVCHandler_C

+2

pw::async2::size_report::MockTask::~MockTask()

+2

pw::containers::internal::IntrusiveListItemBase<>::~IntrusiveListItemBase()

DEL

-20

pw::async2::size_report::PendableValue<>::Get()::{lambda()#1}::operator()()

+10

pw::async2::FuncTask<>::DoPend()

-2

pw::containers::internal::IntrusiveForwardListItem::DoGetPrevious()

+4

__bi_84

NEW

+144

pw::async2::size_report::SingleTypeValueFuture()

NEW

+92

pw::async2::internal::PendValueFutureCore()

NEW

+56

pw::async2::ValueProvider<>::Get()

NEW

+52

pw::async2::ValueFuture<>::Pend()

NEW

+48

pw::async2::ValueFuture<>::ResolveLocked<>()

NEW

+44

pw::async2::BaseFutureList::PushRequireEmpty()

NEW

+44

pw::async2::ValueProvider<>::Resolve<>()

NEW

+40

pw::async2::ValueProvider<>::~ValueProvider()

NEW

+36

pw::async2::ValueFuture<>::~ValueFuture()

NEW

+24

pw::containers::internal::IntrusiveListItemBase<>::unlist()

NEW

+18

pw::async2::FutureCore::~FutureCore()

NEW

+16

pw::async2::FutureCore::WakeAndMarkReady()

NEW

+10

pw::async2::FutureCore::Unlist()

+672

RAM

NEW

+8

pw::async2::internal::ValueProviderLock()::lock

+8

Cost of additional ValueFuture template specialization

FLASH

+8

pw::async2::size_report::Measure()

+56

pw::async2::ValueProvider<>::Get()

+52

pw::async2::ValueFuture<>::Pend()

+48

pw::async2::ValueFuture<>::ResolveLocked<>()

+44

pw::async2::ValueProvider<>::Resolve<>()

+40

pw::async2::ValueProvider<>::~ValueProvider()

+36

pw::async2::ValueFuture<>::~ValueFuture()

+30

pw::async2::FuncTask<>::~FuncTask()

+30

pw::async2::FuncTask<>::DoPend()

+20

pw::async2::FuncTask<>

-4

__bi_84

NEW

+152

pw::async2::size_report::MultiTypeValueFuture()

NEW

+80

__aeabi_f2iz

+592

Size of VoidFuture (ValueFuture<void>)

FLASH

+208

[section .rodata]

-92

pw::async2::size_report::Measure()

DEL

-72

pw::async2::size_report::PendableValue<>::Get()

-8

vPortSVCHandler_C

DEL

-20

pw::async2::size_report::PendableValue<>::Get()::{lambda()#1}::operator()()

-2

pw::async2::FuncTask<>::DoPend()

-2

pw::containers::internal::IntrusiveForwardListItem::DoGetPrevious()

NEW

+128

pw::async2::size_report::VoidFutureReport()

NEW

+92

pw::async2::internal::PendValueFutureCore()

NEW

+52

pw::async2::ValueProvider<>::Get()

NEW

+44

pw::async2::BaseFutureList::PushRequireEmpty()

NEW

+40

pw::async2::ValueFuture<>::Pend()

NEW

+40

pw::async2::ValueProvider<>::~ValueProvider()

NEW

+36

pw::async2::ValueFuture<>::~ValueFuture()

NEW

+32

pw::async2::ValueProvider<>::Resolve<>()

NEW

+24

pw::containers::internal::IntrusiveListItemBase<>::unlist()

NEW

+20

pw::async2::BaseFutureList::ResolveOne()

NEW

+18

pw::async2::FutureCore::~FutureCore()

NEW

+14

pw::async2::BaseFutureList::ResolveOneIfAvailable()

NEW

+14

pw::async2::FutureCore::WakeAndMarkReady()

NEW

+10

pw::async2::FutureCore::Unlist()

+576

RAM

NEW

+8

pw::async2::internal::ValueProviderLock()::lock

+8

async2 utilities#

Pigweed provides several utilities to simplify writing asynchronous code. Among these are combinators which operate over several futures, such as Join which waits for all futures to complete, and Select which waits for the first future to complete.

The table below demonstrates the code size impact of using these utilities. For both Join and Select, the report shows:

  • The initial cost of using the utility with multiple futures of the same type.

  • The incremental cost of adding a second call with futures of different types, which demonstrates the overhead of template specialization.

Additionally, the table includes a comparison showing the code size difference between using the Select helper versus manually polling each future.

Label

Segment

Delta

Size of calling Select() with several futures of the same type

FLASH

+128

[section .rodata]

+8

pw::async2::size_report::Measure()

+86

pw::async2::FuncTask<>::DoPend()

-2

pw::containers::internal::IntrusiveListItemBase<>::~IntrusiveListItemBase()

+30

pw::async2::FuncTask<>::~FuncTask()

+20

pw::async2::FuncTask<>

+4

__bi_84

-4

main

NEW

+200

pw::async2::size_report::SingleTypeSelect()

NEW

+152

pw::async2::SelectFuture<>::PendFuture<>()

NEW

+146

pw::async2::SelectFuture<>::Pend()

NEW

+108

pw::OptionalTuple<>::value<>()

NEW

+36

pw::OptionalTuple<>::UninitializedMoveFrom<>()

NEW

+36

pw::async2::SelectFuture<>::PendAll<>()

NEW

+36

std::__2::__memberwise_forward_assign[abi:nqn240000]<>()

NEW

+36

std::__2::__tuple_impl<>::__tuple_impl[abi:nqn240000]<>()

NEW

+32

pw::async2::ValueFuture<>::is_complete()

NEW

+28

std::__2::__tuple_impl<>::~__tuple_impl()

NEW

+26

pw::OptionalTuple<>::OptionalTuple()

NEW

+16

std::__2::tuple<>::tuple[abi:nqn240000]<>()

NEW

+14

pw::async2::SelectFuture<>::SelectFuture()

NEW

+12

std::__2::optional<>::optional[abi:nqn240000]<>()

NEW

+12

std::__2::tuple<>::operator=[abi:nqn240000]()

+1,160

Size of an additional a call to Select() with futures of different types

FLASH

+84

pw::async2::FuncTask<>::DoPend()

+8

pw::async2::size_report::Measure()

+144

pw::async2::SelectFuture<>::PendFuture<>()

+142

pw::async2::SelectFuture<>::Pend()

+108

pw::OptionalTuple<>::value<>()

+30

pw::async2::FuncTask<>::~FuncTask()

-12

vPortSVCHandler_C

+20

pw::async2::FuncTask<>

+36

pw::OptionalTuple<>::UninitializedMoveFrom<>()

+36

pw::async2::SelectFuture<>::PendAll<>()

+36

std::__2::__memberwise_forward_assign[abi:nqn240000]<>()

+34

std::__2::__tuple_impl<>::__tuple_impl[abi:nqn240000]<>()

+64

pw::async2::ValueFuture<>::is_complete()

+26

std::__2::__tuple_impl<>::~__tuple_impl()

+22

pw::OptionalTuple<>::OptionalTuple()

-4

__bi_84

+16

std::__2::tuple<>::tuple[abi:nqn240000]<>()

+14

pw::async2::SelectFuture<>::SelectFuture()

+12

std::__2::optional<>::optional[abi:nqn240000]<>()

+12

std::__2::tuple<>::operator=[abi:nqn240000]()

NEW

+196

pw::async2::size_report::MultiTypeSelect()

+1,024

Cost of using Select() versus manually polling each future

FLASH

+128

[section .rodata]

+28

pw::async2::size_report::SelectComparisonTask::DoPend()

+8

vPortSVCHandler_C

-2

pw::containers::internal::IntrusiveListItemBase<>::~IntrusiveListItemBase()

NEW

+144

pw::async2::SelectFuture<>::PendFuture<>()

NEW

+142

pw::async2::SelectFuture<>::Pend()

NEW

+108

pw::OptionalTuple<>::value<>()

NEW

+96

pw::async2::ValueFuture<>::is_complete()

NEW

+36

pw::OptionalTuple<>::UninitializedMoveFrom<>()

NEW

+36

pw::async2::SelectFuture<>::PendAll<>()

NEW

+36

std::__2::__memberwise_forward_assign[abi:nqn240000]<>()

NEW

+34

std::__2::__tuple_impl<>::__tuple_impl[abi:nqn240000]<>()

NEW

+26

std::__2::__tuple_impl<>::~__tuple_impl()

NEW

+22

pw::OptionalTuple<>::OptionalTuple()

NEW

+16

std::__2::tuple<>::tuple[abi:nqn240000]<>()

NEW

+14

pw::async2::SelectFuture<>::SelectFuture()

NEW

+12

std::__2::optional<>::optional[abi:nqn240000]<>()

NEW

+12

std::__2::tuple<>::operator=[abi:nqn240000]()

+896

Size of calling Join() with several futures of the same type

FLASH

+104

[section .rodata]

+8

pw::async2::size_report::Measure()

+36

pw::async2::FuncTask<>::DoPend()

-4

vPortSVCHandler_C

+30

pw::async2::FuncTask<>::~FuncTask()

+20

pw::async2::FuncTask<>

+4

__bi_84

-4

main

NEW

+200

pw::async2::size_report::SingleTypeJoin()

NEW

+100

pw::async2::JoinFuture<>::PendElement<>()

NEW

+84

pw::async2::JoinFuture<>::Pend()

NEW

+52

pw::async2::JoinFuture<>::PendElements<>()

NEW

+48

std::__2::__optional_storage_base<>::__assign_from[abi:nqn240000]<>()

NEW

+36

std::__2::__tuple_impl<>::__tuple_impl[abi:nqn240000]<>()

NEW

+28

std::__2::__tuple_impl<>::~__tuple_impl()

NEW

+26

pw::async2::JoinFuture<>::JoinFuture()

NEW

+16

std::__2::tuple<>::tuple[abi:nqn240000]<>()

+784

Size of an additional a call to Join() with futures of different types

FLASH

+8

pw::async2::size_report::Measure()

+32

pw::async2::FuncTask<>::DoPend()

+88

pw::async2::JoinFuture<>::PendElement<>()

+80

pw::async2::JoinFuture<>::Pend()

+30

pw::async2::FuncTask<>::~FuncTask()

-8

vPortSVCHandler_C

+52

pw::async2::JoinFuture<>::PendElements<>()

+48

std::__2::__optional_storage_base<>::__assign_from[abi:nqn240000]<>()

+20

pw::async2::FuncTask<>

+34

std::__2::__tuple_impl<>::__tuple_impl[abi:nqn240000]<>()

+26

std::__2::__tuple_impl<>::~__tuple_impl()

+26

pw::async2::JoinFuture<>::JoinFuture()

-4

__bi_84

+16

std::__2::tuple<>::tuple[abi:nqn240000]<>()

NEW

+208

pw::async2::size_report::MultiTypeJoin()

+656

Channel#

pw_async2 channels are the primary mechanism for communicating between async tasks and threads.

The following size report shows the base cost of using static and dynamic channels, as well as the marginal cost of adding a new channel of a trivial or non-trivial type.

Label

Segment

Delta

Size of static MpmcChannel

FLASH

+436

[section .rodata]

DEL

-248

pw::async2::size_report::Measure()

DEL

-72

pw::async2::size_report::PendableValue<>::Get()

DEL

-60

pw::async2::Waker::operator=()

DEL

-52

pw::async2::size_report::MockTask::DoPend()

DEL

-46

pw::async2::size_report::MockTask::~MockTask()

+30

pw::async2::FuncTask<>::~FuncTask()

DEL

-28

pw::async2::RunnableDispatcher::RunToCompletion()

+20

pw::async2::FuncTask<>

DEL

-20

pw::async2::size_report::MockTask

DEL

-20

pw::async2::size_report::MockTask::DoPend()::{lambda()#1}::operator()()

DEL

-20

pw::async2::size_report::PendableValue<>::Get()::{lambda()#1}::operator()()

+2

pw::async2::FuncTask<>::DoPend()

+2

pw::containers::internal::GenericIntrusiveList<>::push_back()

-2

pw::containers::internal::IntrusiveForwardListItem::DoGetPrevious()

+2

pw::async2::BasicDispatcher::DoWaitForWake()

+4

main

NEW

+256

pw::async2::size_report::MeasureStatic<>()

NEW

+144

pw::async2::SendFuture<>::DoPend()

NEW

+132

pw::async2::ReceiveFuture<>::DoPend()

NEW

+108

pw::async2::internal::BaseChannelFuture::BaseChannelFuture()

NEW

+96

pw::async2::internal::BaseChannelFuture::StoreWakerForReceiveIfOpen()

NEW

+88

pw::async2::internal::BaseChannel::remove_object()

NEW

+76

pw::async2::internal::BaseChannel::~BaseChannel()

NEW

+72

pw::async2::internal::BaseChannelFuture::StoreWakerForSend()

NEW

+68

pw::async2::CreateMpmcChannel<>()

NEW

+52

pw::async2::internal::BaseChannel::add_object()

NEW

+46

pw::async2::size_report::MeasureStatic<>()::{lambda()#1}::operator()()

NEW

+44

pw::async2::ChannelHandle<>::CreateReceiver()

NEW

+44

pw::async2::ChannelHandle<>::CreateSender()

NEW

+44

pw::async2::internal::BaseChannel::add_ref()

NEW

+44

pw::containers::internal::GenericDeque<>::front()

NEW

+44

pw::containers::internal::GenericDeque<>::pop_front()

NEW

+42

pw::async2::internal::Channel<>::CreateReceiver()

NEW

+42

pw::async2::internal::Channel<>::CreateSender()

NEW

+42

pw::async2::size_report::MeasureStatic<>()::{lambda()#2}::operator()()

NEW

+40

pw::async2::internal::BaseChannel::BaseChannel()

NEW

+40

pw::async2::internal::ChannelFuture<>::Pend()

NEW

+40

pw::containers::internal::GenericDeque<>::push_back()

NEW

+36

pw::async2::internal::BaseChannel::RemoveRefAndDestroyIfUnreferenced()

NEW

+36

pw::containers::internal::GenericDeque<>::try_emplace_back<>()

NEW

+34

pw::async2::internal::BaseChannelFuture::StoreAndAddRefIfNonnull()

NEW

+32

pw::FixedDeque<>::~FixedDeque()

NEW

+32

pw::async2::Dispatcher::Dispatcher()

NEW

+32

pw::async2::internal::BaseChannelStorage<>::BaseChannelStorage()

NEW

+32

pw::async2::internal::Channel<>::Channel<>()

NEW

+32

pw::async2::internal::Channel<>::PopAndWake()

NEW

+32

pw::async2::internal::Channel<>::~Channel()

NEW

+30

pw::async2::internal::BaseChannelFuture::RemoveFromChannel()

NEW

+28

pw::async2::BaseFutureList::ResolveAll()

NEW

+28

pw::async2::RunnableDispatcher

NEW

+28

pw::async2::internal::BaseChannel::should_close()

NEW

+24

pw::async2::BasicDispatcher::BasicDispatcher()

NEW

+24

pw::async2::internal::BaseChannel::CloseLocked()

NEW

+24

pw::containers::internal::GenericDequeBase<>::PopFront()

NEW

+24

pw::containers::internal::GenericDequeBase<>::PushBack()

NEW

+24

pw::containers::internal::IntrusiveListItemBase<>::unlist()

NEW

+20

pw::async2::BaseFutureList::ResolveOne()

NEW

+20

pw::async2::ChannelStorage<>::ChannelStorage()

NEW

+20

pw::async2::Receiver<>::Disconnect()

NEW

+20

pw::async2::RunnableDispatcher::RunnableDispatcher()

NEW

+20

pw::async2::SendFuture<>::SendFuture()

NEW

+20

pw::async2::Sender<>::Disconnect()

NEW

+20

pw::async2::internal::BaseChannelHandle::Release()

NEW

+20

pw::async2::internal::Channel<>::PushAndWake<>()

NEW

+20

pw::containers::internal::GenericDeque<>::EmplaceBackUnchecked<>()

NEW

+18

pw::async2::FutureCore::~FutureCore()

NEW

+18

pw::async2::ReceiveFuture<>::~ReceiveFuture()

NEW

+18

pw::async2::Receiver<>::~Receiver()

NEW

+18

pw::async2::SendFuture<>::~SendFuture()

NEW

+18

pw::async2::Sender<>::~Sender()

NEW

+16

pw::async2::internal::BaseChannelFuture::Complete()

NEW

+14

pw::async2::BaseFutureList::ResolveOneIfAvailable()

NEW

+14

pw::async2::FutureCore::WakeAndMarkReady()

NEW

+14

pw::async2::internal::BaseChannel::add_handle()

NEW

+12

pw::async2::ChannelStorage<>

NEW

+12

pw::async2::internal::BaseChannel

NEW

+12

pw::async2::internal::BaseChannel::add_receiver()

NEW

+12

pw::async2::internal::BaseChannel::add_sender()

NEW

+12

pw::async2::internal::BaseChannel::remove_handle()

NEW

+12

pw::async2::internal::BaseChannel::remove_receiver()

NEW

+12

pw::async2::internal::BaseChannel::remove_sender()

NEW

+12

pw::async2::internal::BaseChannelStorage<>

NEW

+12

pw::async2::internal::Channel<>

NEW

+10

pw::async2::FutureCore::Unlist()

NEW

+10

pw::async2::ReceiveFuture<>::ReceiveFuture()

NEW

+10

pw::async2::Receiver<>::Receive()

NEW

+10

pw::async2::Sender<>::Send<>()

NEW

+2

pw::async2::RunnableDispatcher::~RunnableDispatcher()

NEW

+2

pw::async2::internal::BaseChannel::Destroy()

+2,544

RAM

DEL

-32

pw::async2::size_report::(anonymous namespace)::dispatcher

-32

Cost of additional static MpmcChannel<unsigned> instantiation

FLASH

+256

pw::async2::size_report::MeasureStatic<>()

+144

pw::async2::SendFuture<>::DoPend()

+132

pw::async2::ReceiveFuture<>::DoPend()

+68

pw::async2::CreateMpmcChannel<>()

+60

pw::async2::FuncTask<>::~FuncTask()

-8

vPortSVCHandler_C

+46

pw::async2::size_report::MeasureStatic<>()::{lambda()#1}::operator()()

+44

pw::async2::ChannelHandle<>::CreateReceiver()

+44

pw::async2::ChannelHandle<>::CreateSender()

+44

pw::containers::internal::GenericDeque<>::front()

+44

pw::containers::internal::GenericDeque<>::pop_front()

+42

pw::async2::internal::Channel<>::CreateReceiver()

+42

pw::async2::internal::Channel<>::CreateSender()

+40

pw::async2::size_report::MeasureStatic<>()::{lambda()#2}::operator()()

+40

pw::async2::FuncTask<>

+40

pw::async2::internal::ChannelFuture<>::Pend()

+40

pw::containers::internal::GenericDeque<>::push_back()

+36

pw::containers::internal::GenericDeque<>::try_emplace_back<>()

+32

pw::FixedDeque<>::~FixedDeque()

+32

pw::async2::internal::BaseChannelStorage<>::BaseChannelStorage()

+32

pw::async2::internal::Channel<>::Channel<>()

+32

pw::async2::internal::Channel<>::PopAndWake()

+32

pw::async2::internal::Channel<>::~Channel()

+20

pw::async2::ChannelStorage<>::ChannelStorage()

+20

pw::async2::FuncTask<>::DoPend()

+20

pw::async2::Receiver<>::Disconnect()

+20

pw::async2::SendFuture<>::SendFuture()

+20

pw::async2::Sender<>::Disconnect()

+20

pw::async2::internal::Channel<>::PushAndWake<>()

+20

pw::containers::internal::GenericDeque<>::EmplaceBackUnchecked<>()

+18

pw::async2::ReceiveFuture<>::~ReceiveFuture()

+18

pw::async2::Receiver<>::~Receiver()

+18

pw::async2::SendFuture<>::~SendFuture()

+18

pw::async2::Sender<>::~Sender()

+4

__bi_84

+4

main

+12

pw::async2::ChannelStorage<>

+12

pw::async2::internal::BaseChannelStorage<>

+12

pw::async2::internal::Channel<>

+10

pw::async2::ReceiveFuture<>::ReceiveFuture()

+10

pw::async2::Receiver<>::Receive()

+10

pw::async2::Sender<>::Send<>()

+1,600

Cost of additional static MpmcChannel<MoveOnly> instantiation

FLASH

+256

pw::async2::size_report::MeasureStatic<>()

+144

pw::async2::SendFuture<>::DoPend()

+132

pw::async2::ReceiveFuture<>::DoPend()

+68

pw::async2::CreateMpmcChannel<>()

+60

pw::async2::FuncTask<>::~FuncTask()

-8

vPortSVCHandler_C

+46

pw::async2::size_report::MeasureStatic<>()::{lambda()#1}::operator()()

+44

pw::async2::ChannelHandle<>::CreateReceiver()

+44

pw::async2::ChannelHandle<>::CreateSender()

+44

pw::containers::internal::GenericDeque<>::front()

+44

pw::containers::internal::GenericDeque<>::pop_front()

+42

pw::async2::internal::Channel<>::CreateReceiver()

+42

pw::async2::internal::Channel<>::CreateSender()

+40

pw::async2::size_report::MeasureStatic<>()::{lambda()#2}::operator()()

+40

pw::async2::FuncTask<>

+40

pw::async2::internal::ChannelFuture<>::Pend()

+40

pw::containers::internal::GenericDeque<>::push_back()

+36

pw::containers::internal::GenericDeque<>::try_emplace_back<>()

+32

pw::FixedDeque<>::~FixedDeque()

+32

pw::async2::internal::BaseChannelStorage<>::BaseChannelStorage()

+32

pw::async2::internal::Channel<>::Channel<>()

+32

pw::async2::internal::Channel<>::PopAndWake()

+32

pw::async2::internal::Channel<>::~Channel()

+20

pw::async2::ChannelStorage<>::ChannelStorage()

+20

pw::async2::FuncTask<>::DoPend()

+20

pw::async2::Receiver<>::Disconnect()

+20

pw::async2::SendFuture<>::SendFuture()

+20

pw::async2::Sender<>::Disconnect()

+20

pw::async2::internal::Channel<>::PushAndWake<>()

+20

pw::containers::internal::GenericDeque<>::EmplaceBackUnchecked<>()

+18

pw::async2::ReceiveFuture<>::~ReceiveFuture()

+18

pw::async2::Receiver<>::~Receiver()

+18

pw::async2::SendFuture<>::~SendFuture()

+18

pw::async2::Sender<>::~Sender()

+4

__bi_84

+4

main

+12

pw::async2::ChannelStorage<>

+12

pw::async2::internal::BaseChannelStorage<>

+12

pw::async2::internal::Channel<>

+10

pw::async2::ReceiveFuture<>::ReceiveFuture()

+10

pw::async2::Receiver<>::Receive()

+10

pw::async2::Sender<>::Send<>()

+1,600

Size of dynamic MpmcChannel

FLASH

+416

[section .rodata]

DEL

-248

pw::async2::size_report::Measure()

DEL

-72

pw::async2::size_report::PendableValue<>::Get()

DEL

-60

pw::async2::Waker::operator=()

-8

vPortSVCHandler_C

DEL

-52

pw::async2::size_report::MockTask::DoPend()

DEL

-46

pw::async2::size_report::MockTask::~MockTask()

+30

pw::async2::FuncTask<>::~FuncTask()

DEL

-28

pw::async2::RunnableDispatcher::RunToCompletion()

+20

pw::async2::FuncTask<>

DEL

-20

pw::async2::size_report::MockTask

DEL

-20

pw::async2::size_report::MockTask::DoPend()::{lambda()#1}::operator()()

DEL

-20

pw::async2::size_report::PendableValue<>::Get()::{lambda()#1}::operator()()

+68

pw::async2::FuncTask<>::DoPend()

+2

pw::containers::internal::GenericIntrusiveList<>::push_back()

-2

pw::containers::internal::IntrusiveForwardListItem::DoGetPrevious()

+2

pw::async2::BasicDispatcher::DoWaitForWake()

+4

main

NEW

+252

pw::async2::size_report::MeasureDynamic()

NEW

+144

pw::async2::SendFuture<>::DoPend()

NEW

+132

pw::async2::ReceiveFuture<>::DoPend()

NEW

+110

pw::async2::internal::BaseChannelFuture::BaseChannelFuture()

NEW

+96

pw::async2::internal::BaseChannelFuture::StoreWakerForReceiveIfOpen()

NEW

+88

pw::async2::internal::BaseChannel::remove_object()

NEW

+76

pw::async2::internal::BaseChannel::~BaseChannel()

NEW

+72

pw::async2::internal::BaseChannelFuture::StoreWakerForSend()

NEW

+64

pw::async2::CreateMpmcChannel<>()

NEW

+52

pw::FixedDeque<>::TryAllocate()

NEW

+52

pw::async2::internal::BaseChannel::add_object()

NEW

+48

pw::async2::internal::DynamicChannel<>::Allocate()

NEW

+44

pw::async2::ChannelHandle<>::CreateReceiver()

NEW

+44

pw::async2::ChannelHandle<>::CreateSender()

NEW

+44

pw::async2::internal::BaseChannel::add_ref()

NEW

+44

pw::containers::internal::Aligned<>::Align()

NEW

+44

pw::containers::internal::GenericDeque<>::front()

NEW

+44

pw::containers::internal::GenericDeque<>::pop_front()

NEW

+42

pw::async2::internal::Channel<>::CreateReceiver()

NEW

+42

pw::async2::internal::Channel<>::CreateSender()

NEW

+40

pw::async2::internal::BaseChannel::BaseChannel()

NEW

+40

pw::async2::internal::ChannelFuture<>::Pend()

NEW

+40

pw::containers::internal::GenericDeque<>::push_back()

NEW

+36

pw::async2::internal::BaseChannel::RemoveRefAndDestroyIfUnreferenced()

NEW

+36

pw::async2::internal::Channel<>::Channel()

NEW

+36

pw::containers::internal::GenericDeque<>::try_emplace_back<>()

NEW

+34

pw::FixedDeque<>::FixedDeque()

NEW

+34

pw::async2::internal::BaseChannelFuture::StoreAndAddRefIfNonnull()

NEW

+32

pw::FixedDeque<>::~FixedDeque()

NEW

+32

pw::async2::Dispatcher::Dispatcher()

NEW

+32

pw::async2::internal::Channel<>::PopAndWake()

NEW

+32

pw::async2::internal::Channel<>::~Channel()

NEW

+30

pw::Deque<>::Deque()

NEW

+30

pw::async2::internal::BaseChannelFuture::RemoveFromChannel()

NEW

+28

pw::async2::BaseFutureList::ResolveAll()

NEW

+28

pw::async2::RunnableDispatcher

NEW

+28

pw::async2::internal::BaseChannel::should_close()

NEW

+28

pw::async2::internal::ChannelDeque<>::TryAllocate()

NEW

+28

pw::containers::internal::GenericDequeBase<>::MoveAssignIndices()

NEW

+24

pw::Allocator::New<>()

NEW

+24

pw::async2::BasicDispatcher::BasicDispatcher()

NEW

+24

pw::async2::internal::BaseChannel::CloseLocked()

NEW

+24

pw::async2::internal::DynamicChannel<>::Destroy()

NEW

+24

pw::containers::internal::GenericDequeBase<>::PopFront()

NEW

+24

pw::containers::internal::GenericDequeBase<>::PushBack()

NEW

+24

pw::containers::internal::IntrusiveListItemBase<>::unlist()

NEW

+20

pw::allocator::Layout::Of<>()

NEW

+20

pw::async2::BaseFutureList::ResolveOne()

NEW

+20

pw::async2::Receiver<>::Disconnect()

NEW

+20

pw::async2::RunnableDispatcher::RunnableDispatcher()

NEW

+20

pw::async2::SendFuture<>::SendFuture()

NEW

+20

pw::async2::Sender<>::Disconnect()

NEW

+20

pw::async2::internal::BaseChannelHandle::Release()

NEW

+20

pw::async2::internal::Channel<>::PushAndWake<>()

NEW

+20

pw::async2::internal::DynamicChannel<>::DynamicChannel()

NEW

+20

pw::containers::internal::GenericDeque<>::EmplaceBackUnchecked<>()

NEW

+20

std::__2::__optional_destruct_base<>::~__optional_destruct_base[abi:nqn240000]()

NEW

+18

pw::async2::FutureCore::~FutureCore()

NEW

+18

pw::async2::ReceiveFuture<>::~ReceiveFuture()

NEW

+18

pw::async2::Receiver<>::~Receiver()

NEW

+18

pw::async2::SendFuture<>::~SendFuture()

NEW

+18

pw::async2::Sender<>::~Sender()

NEW

+16

pw::Deque<>::MoveBufferFrom()

NEW

+16

pw::async2::internal::BaseChannelFuture::Complete()

NEW

+14

pw::async2::BaseFutureList::ResolveOneIfAvailable()

NEW

+14

pw::async2::FutureCore::WakeAndMarkReady()

NEW

+12

pw::async2::internal::BaseChannel

NEW

+12

pw::async2::internal::BaseChannel::add_handle()

NEW

+12

pw::async2::internal::BaseChannel::add_receiver()

NEW

+12

pw::async2::internal::BaseChannel::add_sender()

NEW

+12

pw::async2::internal::BaseChannel::remove_handle()

NEW

+12

pw::async2::internal::BaseChannel::remove_receiver()

NEW

+12

pw::async2::internal::BaseChannel::remove_sender()

NEW

+12

pw::async2::internal::Channel<>

NEW

+12

pw::async2::internal::DynamicChannel<>

NEW

+10

pw::async2::FutureCore::Unlist()

NEW

+10

pw::async2::ReceiveFuture<>::ReceiveFuture()

NEW

+10

pw::async2::Receiver<>::Receive()

NEW

+10

pw::async2::Sender<>::Send<>()

NEW

+4

pw::async2::internal::BaseChannel::Destroy()

NEW

+2

pw::async2::RunnableDispatcher::~RunnableDispatcher()

+2,816

RAM

DEL

-32

pw::async2::size_report::(anonymous namespace)::dispatcher

-32

Cost of static MpmcChannel when dynamic of same type is present

FLASH

+20

[section .rodata]

+20

pw::async2::FuncTask<>::DoPend()

+68

pw::async2::CreateMpmcChannel<>()

+60

pw::async2::FuncTask<>::~FuncTask()

+12

vPortSVCHandler_C

+40

pw::async2::FuncTask<>

+4

__bi_84

+4

main

+2

pw::async2::internal::BaseChannel::add_handle()

-2

pw::async2::internal::BaseChannel::Destroy()

NEW

+256

pw::async2::size_report::MeasureStatic<>()

NEW

+46

pw::async2::size_report::MeasureStatic<>()::{lambda()#1}::operator()()

NEW

+42

pw::async2::size_report::MeasureStatic<>()::{lambda()#2}::operator()()

NEW

+32

pw::async2::internal::BaseChannelStorage<>::BaseChannelStorage()

NEW

+32

pw::async2::internal::Channel<>::Channel<>()

NEW

+20

pw::async2::ChannelStorage<>::ChannelStorage()

NEW

+12

pw::async2::ChannelStorage<>

NEW

+12

pw::async2::internal::BaseChannelStorage<>

+680

Size of MpmcChannel<void>

FLASH

+296

[section .rodata]

DEL

-248

pw::async2::size_report::Measure()

DEL

-72

pw::async2::size_report::PendableValue<>::Get()

DEL

-60

pw::async2::Waker::operator=()

+4

vPortSVCHandler_C

DEL

-52

pw::async2::size_report::MockTask::DoPend()

DEL

-46

pw::async2::size_report::MockTask::~MockTask()

+30

pw::async2::FuncTask<>::~FuncTask()

DEL

-28

pw::async2::RunnableDispatcher::RunToCompletion()

+20

pw::async2::FuncTask<>

DEL

-20

pw::async2::size_report::MockTask

DEL

-20

pw::async2::size_report::MockTask::DoPend()::{lambda()#1}::operator()()

DEL

-20

pw::async2::size_report::PendableValue<>::Get()::{lambda()#1}::operator()()

+2

pw::async2::FuncTask<>::DoPend()

+2

pw::containers::internal::GenericIntrusiveList<>::push_back()

-2

pw::containers::internal::IntrusiveForwardListItem::DoGetPrevious()

+4

__bi_84

+2

pw::async2::BasicDispatcher::DoWaitForWake()

+4

main

NEW

+256

pw::async2::size_report::MeasureStatic<>()

NEW

+140

pw::async2::SendFuture<>::DoPend()

NEW

+120

pw::async2::ReceiveFuture<>::DoPend()

NEW

+108

pw::async2::internal::BaseChannelFuture::BaseChannelFuture()

NEW

+96

pw::async2::internal::BaseChannelFuture::StoreWakerForReceiveIfOpen()

NEW

+88

pw::async2::internal::BaseChannel::remove_object()

NEW

+76

pw::async2::internal::BaseChannel::~BaseChannel()

NEW

+72

pw::async2::internal::BaseChannelFuture::StoreWakerForSend()

NEW

+68

pw::async2::CreateMpmcChannel<>()

NEW

+52

pw::async2::internal::BaseChannel::add_object()

NEW

+44

pw::async2::ChannelHandle<>::CreateReceiver()

NEW

+44

pw::async2::ChannelHandle<>::CreateSender()

NEW

+44

pw::async2::internal::BaseChannel::add_ref()

NEW

+44

pw::async2::internal::ChannelDeque<>::push_back()

NEW

+42

pw::async2::internal::Channel<>::CreateReceiver()

NEW

+42

pw::async2::internal::Channel<>::CreateSender()

NEW

+40

pw::async2::internal::BaseChannel::BaseChannel()

NEW

+40

pw::async2::internal::ChannelDeque<>::pop_front()

NEW

+40

pw::async2::size_report::MeasureStatic<>()::{lambda()#1}::operator()()

NEW

+40

pw::async2::size_report::MeasureStatic<>()::{lambda()#2}::operator()()

NEW

+36

pw::async2::internal::BaseChannel::RemoveRefAndDestroyIfUnreferenced()

NEW

+36

pw::async2::internal::ChannelFuture<>::Pend()

NEW

+34

pw::async2::internal::BaseChannelFuture::StoreAndAddRefIfNonnull()

NEW

+32

pw::async2::Dispatcher::Dispatcher()

NEW

+30

pw::async2::internal::BaseChannelFuture::RemoveFromChannel()

NEW

+28

pw::async2::BaseFutureList::ResolveAll()

NEW

+28

pw::async2::RunnableDispatcher

NEW

+28

pw::async2::internal::BaseChannel::should_close()

NEW

+28

pw::async2::internal::BaseChannelStorage<>::BaseChannelStorage()

NEW

+28

pw::async2::internal::Channel<>::Channel()

NEW

+24

pw::async2::BasicDispatcher::BasicDispatcher()

NEW

+24

pw::async2::internal::BaseChannel::CloseLocked()

NEW

+24

pw::containers::internal::IntrusiveListItemBase<>::unlist()

NEW

+20

pw::async2::BaseFutureList::ResolveOne()

NEW

+20

pw::async2::ChannelStorage<>::ChannelStorage()

NEW

+20

pw::async2::Receiver<>::Disconnect()

NEW

+20

pw::async2::RunnableDispatcher::RunnableDispatcher()

NEW

+20

pw::async2::SendFuture<>::~SendFuture()

NEW

+20

pw::async2::Sender<>::Disconnect()

NEW

+20

pw::async2::internal::BaseChannelHandle::Release()

NEW

+20

pw::async2::internal::Channel<>::PopAndWake()

NEW

+20

pw::async2::internal::Channel<>::PushAndWake()

NEW

+18

pw::async2::FutureCore::~FutureCore()

NEW

+18

pw::async2::ReceiveFuture<>::~ReceiveFuture()

NEW

+18

pw::async2::Receiver<>::~Receiver()

NEW

+18

pw::async2::Sender<>::~Sender()

NEW

+18

pw::async2::internal::BaseChannelFuture::Complete()

NEW

+14

pw::async2::BaseFutureList::ResolveOneIfAvailable()

NEW

+14

pw::async2::FutureCore::WakeAndMarkReady()

NEW

+14

pw::async2::internal::BaseChannel::add_handle()

NEW

+12

pw::async2::ChannelStorage<>

NEW

+12

pw::async2::internal::BaseChannel

NEW

+12

pw::async2::internal::BaseChannel::add_receiver()

NEW

+12

pw::async2::internal::BaseChannel::add_sender()

NEW

+12

pw::async2::internal::BaseChannel::remove_handle()

NEW

+12

pw::async2::internal::BaseChannel::remove_receiver()

NEW

+12

pw::async2::internal::BaseChannel::remove_sender()

NEW

+12

pw::async2::internal::BaseChannelStorage<>

NEW

+12

pw::async2::internal::Channel<>

NEW

+10

pw::async2::FutureCore::Unlist()

NEW

+10

pw::async2::ReceiveFuture<>::ReceiveFuture()

NEW

+10

pw::async2::Receiver<>::Receive()

NEW

+10

pw::async2::Sender<>::Send()

NEW

+2

pw::async2::RunnableDispatcher::~RunnableDispatcher()

NEW

+2

pw::async2::internal::BaseChannel::Destroy()

+2,136

RAM

DEL

-32

pw::async2::size_report::(anonymous namespace)::dispatcher

-32

Cost of MpmcChannel<void> with static MpmcChannel<int>

FLASH

+140

[section .rodata]

+256

pw::async2::size_report::MeasureStatic<>()

+144

pw::async2::SendFuture<>::DoPend()

+132

pw::async2::ReceiveFuture<>::DoPend()

+68

pw::async2::CreateMpmcChannel<>()

+60

pw::async2::FuncTask<>::~FuncTask()

-8

vPortSVCHandler_C

+44

pw::async2::ChannelHandle<>::CreateReceiver()

+44

pw::async2::ChannelHandle<>::CreateSender()

+42

pw::async2::internal::Channel<>::CreateReceiver()

+42

pw::async2::internal::Channel<>::CreateSender()

+40

pw::async2::FuncTask<>

+46

pw::async2::size_report::MeasureStatic<>()::{lambda()#1}::operator()()

+42

pw::async2::size_report::MeasureStatic<>()::{lambda()#2}::operator()()

+40

pw::async2::internal::ChannelFuture<>::Pend()

+32

pw::async2::internal::BaseChannelStorage<>::BaseChannelStorage()

+20

pw::async2::ChannelStorage<>::ChannelStorage()

+20

pw::async2::FuncTask<>::DoPend()

+20

pw::async2::Receiver<>::Disconnect()

+18

pw::async2::SendFuture<>::~SendFuture()

+20

pw::async2::Sender<>::Disconnect()

+32

pw::async2::internal::Channel<>::PopAndWake()

+18

pw::async2::ReceiveFuture<>::~ReceiveFuture()

+18

pw::async2::Receiver<>::~Receiver()

+18

pw::async2::Sender<>::~Sender()

-2

pw::async2::internal::BaseChannelFuture::Complete()

+4

main

+12

pw::async2::ChannelStorage<>

+12

pw::async2::internal::BaseChannelStorage<>

+12

pw::async2::internal::Channel<>

+10

pw::async2::ReceiveFuture<>::ReceiveFuture()

+10

pw::async2::Receiver<>::Receive()

NEW

+44

pw::containers::internal::GenericDeque<>::front()

NEW

+44

pw::containers::internal::GenericDeque<>::pop_front()

NEW

+40

pw::containers::internal::GenericDeque<>::push_back()

NEW

+36

pw::containers::internal::GenericDeque<>::try_emplace_back<>()

NEW

+32

pw::FixedDeque<>::~FixedDeque()

NEW

+32

pw::async2::internal::Channel<>::Channel<>()

NEW

+32

pw::async2::internal::Channel<>::~Channel()

NEW

+24

pw::containers::internal::GenericDequeBase<>::PopFront()

NEW

+24

pw::containers::internal::GenericDequeBase<>::PushBack()

NEW

+20

pw::async2::SendFuture<>::SendFuture()

NEW

+20

pw::async2::internal::Channel<>::PushAndWake<>()

NEW

+20

pw::containers::internal::GenericDeque<>::EmplaceBackUnchecked<>()

NEW

+10

pw::async2::Sender<>::Send<>()

+1,784