Azure IoT Hub C SDK is written in ANSI C (C99), which makes it well-suited for a variety of platforms with small disk and memory footprint. We recommend at least 64KB of RAM, but the exact memory footprint depends on the protocol used, the number of connections opened, as well as the platform targeted. This blog walks through how to optimize the C SDK for constrained devices.
We release our C SDK as packages on apt-get, NuGet and MBED to accelerate the development process. However, if your system is constrained in ROM or RAM, you may want to build the SDK locally and remove certain features to shrink the footprint of the C SDK. We will be using cmake to demonstrate in this blog. In addition, the programming model for working with constrained devices is different. This blog will also discuss some best practices to reduce memory consumption. There is also official documentation on how to develop for constrained devices available to you.
Building the C SDK for constrained devices
First, you need to prepare your development environment following this guide. When you get to the step for building with cmake, you can invoke flags to remove certain features.
TL;DR: If you are building for a constrained device, consider using this cmake command:
cmake -Duse_amqp=OFF -Duse_http=OFF -Dno_logging=OFF -Ddont_use_uploadtoblob=ON <Path_to_cmake>
Remove additional protocol libraries
Our SDKs support five protocols today: MQTT, MQTT over WebSocket, AMQPs, AMQP over WebSocket, and HTTPS. Most of our customers have one to two protocols running on a client, hence you can remove the protocol library you are not using from the SDK. There is additional information about choosing the appropriate communication protocol for your scenario. For example, MQTT is a lightweight protocol that is often better suited for constrained devices. In testing, we found that using MQTT instead of AMQP can shrink ROM usage by 50 percent and RAM usage by 20 percent*.
You can remove AMQP and HTTP libraries using the following cmake command:
cmake -Duse_amqp=OFF -Duse_http=OFF <Path_to_cmake>
Remove SDK logging capability
The C SDK provides extensive logging throughout to help with debugging. In testing, we found that disabling logging can shrink ROM usage by 20 percent*. You can remove the logging capability for production devices using the following cmake command:
cmake -Dno_logging=OFF <Path_to_cmake>
Remove upload to blob capability
You can upload large files to Azure Storage using the built-in capability in the SDK. Azure IoT Hub acts as a dispatcher to an associated Azure Storage account. You can use this feature to send media files, large telemetry batches, and logs. Learn more about how to upload files with IoT Hub. If your application does not require this functionality, you can remove this feature using the following cmake command:
cmake -Ddont_use_uploadtoblob=ON <Path_to_cmake>
Running strip on Linux environment
If your binaries run on Linux system, you can leverage the strip command to reduce the size of the final application after compiling.
strip -s <Path_to_executable>
Programming models for constrained devices
Avoid using the Serializer
The C SDK has an optional serializer which allows you to use declarative mapping tables to define methods and device twin properties. This is designed to simplify development, but it adds overhead, which is not optimal for constrained devices. In this case, consider using primitive client APIs and parse json by using a lightweight parser such as parson.
Use the lower layer (_LL_) layer
The C SDK supports two programming models. One set has APIs with an _LL_ infix, which stands for lower layer. This set of APIs are lighter weight and do not spin up worker threads. You must manually control scheduling. The _LL_APIs for device client can be found in this header file. Another set of APIs without the _LL_ index is called the convenience layer, where a worker thread is spun automatically. For example, the convenience layer APIs for device client can be found in this header file. For constrained devices where each extra thread can take a substantial percentage of system resources, consider using _LL_ APIs.
To learn more about Azure IoT C SDK architecture:
*ROM and RAM consumption savings are approximations. The exact usage depends on the protocol used, the number of connections opened, as well as the platform targeted.