<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Articles tagged statemachine at Royyan Dzakiy</title>
  <link rel="alternate" type="text/html"
        href="https://royyandzakiy.com/tags/statemachine/"/>
  <link rel="self" type="application/atom+xml"
        href="https://royyandzakiy.com/tags/statemachine/feed/"/>
  <updated>2026-10-16T09:06:07Z</updated>
  <id>urn:uuid:eb27d36b-1ea1-8fa6-8753-967320235ab4</id>

  <author>
    <name>Royyan Dzakiy</name>
    <uri>https://royyandzakiy.com</uri>
  </author>

  <entry>
    <title>Zephyr Modern C++ - State Machine Size Comparison</title>
    <link rel="alternate" type="text/html" href="https://royyandzakiy.com/blog/2026-01/zephyr-cpp-vs-c-size/"/>
    <id>urn:uuid:0d1c8e4a-824d-5071-81bd-ab33d7526662</id>
    <updated>2026-01-12T00:00:00Z</updated>
    <category term="zephyr"/><category term="cpp"/><category term="statemachine"/>
    <content type="html">
      <![CDATA[<p>Can we use the latest C++ features on microcontrollers? <strong>Yes.</strong></p>

<p>I’ve been testing out to use it on Zephyr and ESP-IDF.</p>

<p>One particular feature I tried out in this example is the use of <code>std::variant</code> for different States, and ultimately using <code>std::visit</code> to iterate through them. Here I provide implementation of a general <code>get_state_info</code> to read what the current state is using the Overloaded Lambda idiom (to enforce availability of all StateVariants), it will then return a <code>std::string_view</code> of different messages based on the <code>current_state_</code>.</p>

<p>Let’s say, a more shiny StateMachine haha. A different approach than using bare enums and switch statements (not simply saying they are less).</p>

<p>Check it out!
<a href="https://github.com/royyandzakiy/zephyr-modern-cpp">https://github.com/royyandzakiy/zephyr-modern-cpp</a></p>

<!--more-->

<p>So far, there is a <strong>540 bytes difference</strong> when using <code>std::variant</code>/<code>std::visit</code>, compared to raw enum/switch.</p>

<p><strong>First build (std::variant/visit):</strong></p>
<ul>
  <li>FLASH: 73,112 bytes (6.97% of 1MB)</li>
  <li>RAM: 53,928 bytes (11.76% of 448KB)</li>
</ul>

<p><strong>Second build (enum/switch)</strong> (code depicted in image below):</p>
<ul>
  <li>FLASH: 72,572 bytes (6.92% of 1MB)</li>
  <li>RAM: 53,928 bytes (11.76% of 448KB)</li>
</ul>

<p>I also tried comparing when adding the C++ library to the compilation, and removing it. There is a <strong>4256 byte addition</strong>.</p>

<p><strong>Third build</strong> (converting all C++ to pure C &amp; but still compiling C++ library in kconfig):</p>
<ul>
  <li>FLASH: 71,588 bytes (6.83% of 1MB)</li>
  <li>RAM: 53,952 bytes (11.76% of 448KB)</li>
</ul>

<p><strong>Fourth build</strong> (converting all C++ to pure C &amp; removing C++ library in kconfig):</p>
<ul>
  <li>FLASH: 67,332 bytes (6.42% of 1MB)</li>
  <li>RAM: 53,840 bytes (11.74% of 448KB)</li>
</ul>

<p><strong>State machine using std::variant, std::visit</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_variant.png" alt="alt text" /></p>

<p><strong>State machine using enum &amp; switch</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_switch.png" alt="alt text" /></p>

<p><strong>Removing most all CPP code, change into C</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_c_cpp.png" alt="alt text" /></p>

<p><strong>Removing CPP lib in prj.conf</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_pure_c.png" alt="alt text" /></p>

<p><strong>Code using enum &amp; switch</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_recode_pure_c.png" alt="alt text" /></p>

<hr />

<p>The variant doesn’t add too much overhead. I was expecting a lot more bytes eaten up just by using Templates itself 😄</p>

<p>cc Srdjan Stokic</p>
]]>
    </content>
  </entry>

</feed>
