Replies: 1 comment
-
I just released v1.3.1 after I figured out how to implement The The MemoryBenchmark shows that On AVR processors, the extra call into In summary, the API breakages from v1.2.4 to v1.3.1 should be fairly minor: 1)) No virtual destructor on |
Beta Was this translation helpful? Give feedback.
-
Folks,
I'm about to release v1.3 of AceRoutine, but it has a number of API breaking changes. The primary motivation for v1.3 is to reduce the flash memory consumption of a
Coroutine
instance as much as possible, particularly on 8-bit AVR processors, while retaining its core functionality.Coroutine
consumes 1098 bytes of flash, and the subsequent instances consume about 228 bytes of flash each.Here are the breaking changes that reduced the resource consumption:
The destructor in the
Coroutine
class is no longervirtual
. This means thatCoroutine
instance cannot be created on the heap using thenew
operator, and cannot be deleted polymorphically. I don't think this will be a problem because this usage has never been tested, and was not documented. This single change decreases flash usage on an AVR processor by about 600 bytes because the virtual destructor pulls inmalloc()
andfree()
.The
COROUTINE_DELAY_MICROS()
micro has been deleted. I personally have never used this feature. I implemented it in Microsecond Timing? #9, but in retrospect, it was a mistake. Because it forces theCOROUTINE_DELAY()
to use aswitch
statement, which increases flash usage by about 30 bytes on every usage ofCOROUTINE_DELAY()
, even ifCOROUTINE_DELAY_MICROS()
is never used in a given program.The
COROUTINE_DELAY_SECONDS()
macro has been deleted. This saves 150-200 bytes of flash on the 1st coroutine, and 10-30 bytes of flash per subsequent instance. This macro uses a division by 1000 operation on a 32-bit millisecond integer counter to keep track of the "seconds". On an 8-bit AVR processor with no hardware division instruction, a software long division on a 32-bit integer is very expensive.The
Coroutine
class no longer saves the human readable name of the coroutine, by removing theCoroutine::mName
field and theCoroutine::getName()
method. This saves about 10-30 bytes of flash (depending on the length of the name string), and 3 bytes of static memory perCoroutine
instance. I had thought that saving the human-readable name would be helpful for debugging, in combination of theCoroutineScheduler::list()
function. But in practice, it has not been very useful, and I don't think it's worth paying the extra resource cost.Updated: With the removal of
Coroutine::mName
, theCoroutine::setupCoroutine()
no longer needs to be called, because the human-readable name no longer needs to be provided through thesetupCoroutine()
method. This method is now marked deprecated, but retained for backwards compatibility. The compiler will print a warning message.Updated: The
Coroutine::coroutineMillis()
method is no longervirtual
. The only reason this method was marked as virtual was to allow the injection of a fakemillis()
function for unit testing purposes. Using some C++ template magic, I am able to use compile-time polymorphism, instead of runtime polymorphism through the virtual dispatch, saving 15-25 bytes of flash (I think per each usage ofCOROUTINE_DELAY()
, but I'm not sure), yet, still be able to inject a fakemillis()
for unit tests. The nice thing about a non-virtualcoroutineMillis()
is that the compiler is able to completely optimize away the extra function call. So thecoroutineMillis()
call becomes optimized into a direct call tomillis()
.In general, a
Coroutine
will always have a higher overhead than a simple function with a non-blocking delay on amillis()
function. But sometimes, an algorithm is far easier to express as a coroutine than using a finite state machine inside a non-blocking function, see USER_GUIDE.md#ComparisonToNonBlockingFunction and the benchmark results in MemoryBenchmark/README.md.I am hoping with the changes made in v1.3, the overhead of the
Coroutine
class is small enough that the tradeoff become more worthwhile in more situations.Beta Was this translation helpful? Give feedback.
All reactions