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
|
+3,224 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RAM
|
+40 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Base incremental cost of adding a task to an existing async system |
FLASH
|
+64 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Size of pw_async2’s C++ coroutine adapters |
FLASH
|
+1,872 |
Futures#
Futures are the core abstraction in
pw_async2, providing a standardized way of polling an asynchronous
operation to completion.
The design of futures has some implications for code size:
All futures are templated on the type of value they produce, which means that the compiler must generate separate code for each type.
Additionally, futures use CRTP for compile-time polymorphism, so each concrete future type is a distinct class and may duplicate common behavior.
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 |
FLASH
|
+728 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RAM
|
+8 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Cost of additional |
FLASH
|
+688 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Size of |
FLASH
|
+632 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RAM
|
+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
|
+1,144 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Size of an additional a call to Select() with futures of different types |
FLASH
|
+1,024 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Cost of using Select() versus manually polling each future |
FLASH
|
+880 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Size of calling Join() with several futures of the same type |
FLASH
|
+832 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Size of an additional a call to Join() with futures of different types |
FLASH
|
+688 |
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 |
FLASH
|
+2,408 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RAM
|
-32 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Cost of additional static |
FLASH
|
+1,584 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Cost of additional static |
FLASH
|
+1,584 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Size of dynamic |
FLASH
|
+2,688 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RAM
|
-32 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Cost of static |
FLASH
|
+664 |