Real-time operating systems (RTOS) are finding their way into more and more systems. Developers who are accustomed to bare-metal development or working with highly resource constrained systems will often complain about system performance or memory usage. Here are seven tips developers can follow to help optimize their RTOS for performance and code size.
1. Minimize Tasks in the Application
The ability to break an application up into separate tasks, “mini programs,” that appear to be running concurrently is extraordinarily beneficial. Developers who are new to RTOS development, though, can sometimes get a little overzealous and create more tasks than are required for the application. What’s the harm in a few extra tasks? Every task that is created in the application requires that a task control block (TCB) be created to manage the task. The TCB contains at least a few dozen different variables that are used to track the task. (An example TCB from uCOS/III can be seen here.) As one can imagine, the TCB doesn’t use a large amount of memory but as more and more tasks are added, the memory use can quickly balloon. For that reason, developers looking to minimize how much code space is used should be looking to minimize how many tasks are in the application.
2. Use Memory Block Pools over Byte Pools
A memory byte pool essentially is a heap. A developer can request memory dynamically during program execution just like they are using malloc. In many cases, using the heap or a byte pool can result in non-deterministic behavior that affects the real-time system performance. In order to ensure that the system runs in a timely manner, developers can use block pools instead which behave in a deterministic manner and also don’t have issues with fragmentation.
3. Don’t Create and Destroy Objects
Creating tasks, semaphores, message queues, and other RTOS objects usually results in memory being allocated dynamically. Creating and destroying RTOS objects will use malloc and free which once again are not deterministic and can result in performance issues. The overhead associated with creating and destroying objects especially if it is done often can be a system hindrance not to mention how it can increase the code complexity and make the program difficult to follow. When possible allocate all objects during the applications initialization and let them persist throughout the applications life. In this way, objects will behave as if they are being allocated statically rather than dynamically.
4. Consider Using Event Flags
Event flags can be used to synchronize tasks similar to the way that a semaphore is used to synchronize tasks. When comparing event flags and semaphores from a performance standpoint, event flags usually use less memory and execute faster. Developers should consider comparing the memory footprints and execution times for their RTOS to determine where they can squeeze a few extra bytes or microseconds from their application.
5. Minimize RTOS Objects
Most RTOS objects require a control block. The more tasks, semaphores, message queues, etc. that are in the application, the greater the memory usage will be.