Last Updated on September 2, 2026

Overview

When developing embedded Linux systems with the Yocto Project® and OpenEmbedded, it is important to note that optimization is typically measured in two distinct dimensions: non-volatile flash storage and runtime physical RAM. Furthermore, while a compiled application may appear incredibly small on the root file system, its actual impact during system execution can reveal a vastly different story. In this study, we take an exhaustive look at a classic compiled example—95.01_hello-cpp—to thoroughly analyze both its storage overhead on the root filesystem (rootfs) and its target physical memory footprint. We combine flash storage delta tracking with low-level kernel system call tracing for this investigation.

Code

hello-cpp_1.0.bb:

DESCRIPTION = "Simple helloworld application"
SECTION = "examples"
SUMMARY = "Simple helloworld application"
HOMEPAGE = "https:/www.ReliableEmbeddedSystems.com"
RECIPE_MAINTAINER = "Robert Berger <Robert.Berger@ReliableEmbeddedSystems.com>"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://COPYING;md5=1d10f40055ab4fb8f37eb56febff1d19"

SRCREV = "5669bcd6894a27e95454aadcea57054dd11b7612"
# upstream:
SRC_URI = "git://gitlab.com/exempli-gratia/hello-cpp.git;protocol=https;branch=master"

do_compile() {
         ${CXX} hello-cpp.cpp ${CFLAGS} ${LDFLAGS} -o hello-cpp
}

do_install() {
         install -d ${D}${bindir}
         install -m 0755 hello-cpp ${D}${bindir}
}

hello-cpp.cpp:

#include <stdlib.h>
#include <iostream>

using namespace std;

int main()
{
    cout << "Hello world from C++ "<< endl;
    return 0;
}

Key Takeaways

  • The Microscopic Flash Profile:
    • On Flash, the C++ binary is highly optimized, requiring only a tiny 3,000-byte compressed package size. It adds a mere 84 KB to the final rootfs layout.
  • The Uninstallation Residuals:
    • Even simple application package removals can leave behind “ghost” artifact files. Standard uninstallation leaves a permanent 8 KB garbage overhead in /etc and opkg status tracking directories.
  • The C++ Runtime Premium:
    • Despite its small storage footprint, loading dependencies and initializing the C++ standard infrastructure demands exactly 2.30 MB of actual, physical target RAM.

Case Study: 95.01_hello-cpp Resource Metrics

Evaluating an application solely on its binary size introduces severe blind spots into embedded architecture planning. Below is the multi-dimensional blueprint of how a basic compiled runtime populates the target system’s flash and RAM.

Root Filesystem (rootfs) Storage Impact

MetricValue
Compressed .ipk Size3,000 Bytes
Runtime Dependencies (RDEPENDS)libc6, libstdc++6
Total Rootfs Size Increase (Delta)+84 KB

Post-(Un)installation

MetricValue
Delta After Standard Package Installation+84 KB
Delta Remaining After Package Uninstallation+8 KB
Permanent Leftover Garbage (Flash Bloat)8 KB

Runtime Physical Memory Profile

Analysis MetricMemory Footprint
True Physical Heap Allocation (brk)2.14 MB
Immediate Active Maps (mmap)0.07 MB
Linker Activation Paths (mprotect)0.10 MB
ESTIMATED REAL TARGET RAM USAGE2.30 MB
Ignored Virtual Address Allocations5.55 MB

Technical Summary: Storage Residuals and Kernel Telemetry

1. The Storage Dilemma: Why is Flash Garbage Left Behind?

When running opkg remove –autoremove && opkg clean, the filesystem layout fails to return completely to its baseline state. The additional 8 KB permanent flash footprint is driven by:

  • The local internal package manager stores changes to /var/lib/opkg/status.
  • There is a slight data growth in target runtime system files like /etc/ld.so.cache.
  • OpenEmbedded includes safety mechanisms that purposely preserve configuration baselines inside /etc.

2. The Runtime Dilemma: Deconstructing System Call Telemetry

By profiling the program execution using perf record, we log the exact interactions between the Linux memory management subsystem and the compiled application binary:

perf record -e syscalls:sys_enter_mmap -e syscalls:sys_enter_mprotect -e syscalls:sys_exit_brk -- hello-cpp
Hello world from C++
[ perf record: Captured and wrote 0.008 MB perf.data (31 samples) ]

Parsing this raw system log with our perf-calc-python3.py script filters out inactive kernel maps to extract three primary resource indicators:

True Heap Growth (brk): 2.14 MB

This tracks the exact amount of physical memory mapped onto the main system heap segment. The binary execution log captures consecutive allocation block boundaries:

hello-cpp 1550: syscalls:sys_exit_brk: 0xaaaadc9dd000
hello-cpp 1550: syscalls:sys_exit_brk: 0xaaaadcc00000

This multi-megabyte heap premium is the mandatory startup tax of the language ecosystem. The C++ Standard Library, therefore, constructs standard core abstractions, subsequently instantiates global input/output buffers (such as ⁣), maps runtime exception handling tables, and, finally, organizes internal static components the millisecond the application enters its execution pathway.

“Immediate Active Maps”: 0.07 MB

These represent physical maps: anonymous, writable. They are instantiated through mmap, which is globally accessible during the execution sweep. Moreover, since our workload is strictly single-threaded, it effectively bypasses the multi-megabyte thread-stack overhead entirely, thereby keeping this pool minimal.

Activated via mprotect: 0.10 MB

This subsequently registers virtual blocks that initial security layers had marked as inaccessible but later transitioned to runtime privileges:

hello-cpp 1550: syscalls:sys_enter_mprotect: start: 0xffffadcff000, len: 0x00011000, prot: 0x0001

Since 95.01_hello-cpp depends on dynamic shared infrastructure (libstdc++.so, libm.so, and libc.so), consequently, the dynamic linker (ld.so) must actively override memory page permissions in order to execute references and establish path routes to static variables across global arrays.

Ignored Virtual Space: 5.55 MB (Filtered Out)

The tracing tool intentionally flags and drops 5.55 MB of memory definitions labeled with PROT_NONE (prot: 0x00000000). Linux reserves massive, continuous address block assignments to safely house the shared libraries without fragmenting the system space. Consequently, as there are no physical RAM chips supporting this allocation, it imposes absolutely no structural stress on your hardware target board.

Practical Conclusion

The architectural analysis of 95.01_hello-cpp yields a critical lesson for custom embedded Linux platform design: package binary sizes are deeply deceptive. In terms of raw storage, a compiled C++ routine is, therefore, an incredibly optimized choice, as it adds less than 100 KB of total footprint to a core-image-minimal target device layout.

However, your physical hardware must be provisioned to handle the inevitable runtime standard library cost. The physical target hardware must supply at least 2.30 MB of active memory just to load code dependencies and open basic data output paths. When architecting hardware modules with strict, low-megabyte constraints, platform engineers must consistently weigh flash budgets side-by-side with dynamic linker initialization tables.

Appendix

To learn how Embedded-Linux works, take a look here. To learn more about the Yocto Project®, take a look here.

Upcoming Events

Our 3 points

of differentiation

We provide host and target hardware during all our teaching.

Three or more people from the same company? We provide private customized training – consulting included.

Subject matter experts develop high-quality, job-related, up-to-date, authentic courseware.

Reliable Embedded Systems
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.